package com.ytjj.qmyx.mall.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gexin.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Joiner;
import com.ytjj.common.api.CommonResult;
import com.ytjj.common.api.ResultCode;
import com.ytjj.common.constants.CopyWriterConstant;
import com.ytjj.common.constants.QueueConstants;
import com.ytjj.common.constants.SysConfigConstants;
import com.ytjj.common.constants.TokenConstants;
import com.ytjj.common.dto.mqdto.SellAfterDto;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.model.UsersResponse;
import com.ytjj.common.service.RedisService;
import com.ytjj.common.utils.CopyWriterConfigUtil;
import com.ytjj.common.utils.HttpClientUtil;
import com.ytjj.common.utils.SysConfigUtil;
import com.ytjj.common.utils.TokenUtil;
import com.ytjj.qmyx.mall.builder.MyBoolQueryBuilder;
import com.ytjj.qmyx.mall.config.SupplyApiConfig;
import com.ytjj.qmyx.mall.constants.*;
import com.ytjj.qmyx.mall.enums.*;
import com.ytjj.qmyx.mall.mapper.*;
import com.ytjj.qmyx.mall.model.*;
import com.ytjj.qmyx.mall.model.dto.RecordSubsidyDataDto;
import com.ytjj.qmyx.mall.model.esmodel.ProductActivityEsDto;
import com.ytjj.qmyx.mall.model.esmodel.ProductEsDto;
import com.ytjj.qmyx.mall.model.request.ProductListRequest;
import com.ytjj.qmyx.mall.model.request.ProductReceiveRequest;
import com.ytjj.qmyx.mall.model.response.*;
import com.ytjj.qmyx.mall.model.vo.HighestVolumeProductVO;
import com.ytjj.qmyx.mall.model.vo.ProductHelpWorkVo;
import com.ytjj.qmyx.mall.model.vo.ProductSpecVO;
import com.ytjj.qmyx.mall.service.*;
import com.ytjj.qmyx.mall.utils.*;
import com.ytjj.qmyx.users.client.UsersClient;
import com.ytjj.qmyx.users.mapper.UsersInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.*;

/**
 * 商品接口实现类
 *
 *
 * @version 1.0
 *
 */
@Service
@Slf4j
@RefreshScope
public class ProductServiceImpl implements ProductService {

    @Resource
    private ProductMapper productMapper;

    private final CommonService commonService;

    @Resource
    private ProductMatchingMapper productMatchingMapper;

    @Resource
    private ProductDao productDao;
    @Resource
    private BannersMapper bannersMapper;

    @Resource
    private ProductImgMapper productImgMapper;

    @Resource
    private ProductSpecMapper productSpecMapper;

    @Resource
    private ProductSpecialMapper productSpecialMapper;

    @Resource
    private BankerMapper bankerMapper;

    @Resource
    private UsersInfoMapper usersInfoMapper;

    @Resource
    private CopyWriterConfigUtil copyWriterConfigUtil;

    @Autowired
    private RedisService redisService;

    @Autowired
    private ProductRecordUtil productRecordUtil;

    @Resource
    private SpecialMapper specialMapper;

    @Autowired
    private ElasticsearchTemplate template;

    @Resource
    private ProductActivitySpecMapper productActivitySpecMapper;

    @Resource
    private ProductBrowsingRecordMapper productBrowsingRecordMapper;
    @Resource
    private PageButtonMapper pageButtonMapper;
    @Resource
    private ProductActivityImgMapper productActivityImgMapper;
    @Resource
    private ProductActivityMapper productActivityMapper;
    @Resource
    private ProductActivityMatchingMapper productActivityMatchingMapper;
    @Resource
    private EsService esService;

    @Resource
    private ProductReviewsMapper productReviewsMapper;

    @Resource
    private EvaluationProductDao evaluationProductDao;

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Value("${recommendProductIds:}")
    private String recommendProductIds;
    @Value("${app.fixPrice:60}")
    private String fixPriceParam;
    @Autowired
    private YxProductGroupBuyInfoService yxProductGroupBuyInfoService;

    @Autowired
    FrontCategoryMapper frontCategoryMapper;

    @Autowired
    FrontCategoryService frontCategoryService;

    @Resource
    ProductSubjectPlateMapper productSubjectPlateMapper;

    @Resource
    private SupplyApiConfig supplyApiConfig;
    @Resource
    private ProductCategoryMapper productCategoryMapper;
    @Resource
    private OrdersService ordersService;


    /**
     * 商品详情缓存key
     */
    public static final String PRODUCT_DETAILS_KEY = "PRODUCT_DETAILS_KEY";

    /**
     * 商品详情页中的品牌商品列表缓存key
     */
    private static final String BRAND_PRODUCT_IN_PRODUCT_DETAILS = "BRAND_PRODUCT_IN_PRODUCT_DETAILS";

    /**
     * 商品详情缓存key(h5)
     */
    private static final String PRODUCT_DETAILS_KEY_H5 = "PRODUCT_DETAILS_KEY_H5";

    public ProductServiceImpl(CommonService commonService) {
        this.commonService = commonService;
    }

    @Override
    public ProductResponse getProductById(Integer id, String modular) {
        String key = RedisConstants.PRODUCT_DETAILS + PRODUCT_DETAILS_KEY + id;
        String result = redisService.get(key);
        ProductResponse productResponse;
        if (result != null) {
            productResponse = com.alibaba.fastjson.JSONObject.parseObject(result, ProductResponse.class);
        } else {
            Product product = productMapper.selectByPrimaryKey(id);
            product.setWarehouseName(null);
            Optional.ofNullable(product).orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
            if (product.getStatus().byteValue() != ProductStatusEnums.UP.getValue()) {
                throw new ApiException(ResultCode.NO_PRODUCT);
            }
            // pv值加+1
            product.setPv(product.getPv() == null ? 1 : product.getPv() + 1);
            productMapper.updateByPrimaryKeySelective(product);

            String productImgRedisKey = RedisConstants.PRODUCT_DETAILS_IMG + PRODUCT_DETAILS_KEY + id;
            String redisJsonStr = redisService.get(productImgRedisKey);
            if (StringUtils.isEmpty(redisJsonStr)) {
                ProductImgExample example = new ProductImgExample();
                example.setOrderByClause("sort asc,id asc");
                example.createCriteria()
                        .andProductIdEqualTo(id);
                List<ProductImg> productImgList = productImgMapper.selectByExample(example);
                Map<String, List<ProductImg>> map = productImgList.stream()
                        .collect(Collectors.groupingBy(ProductImg::getType));
                List<Product> products = new ArrayList<>();
                //品牌
                if (null != product.getSupplyProductId()){
                    ProductReceiveRequest productReceiveRequest = new ProductReceiveRequest();
                    productReceiveRequest.setProductIds(Arrays.asList(product.getSupplyProductId()));
                    String json = com.alibaba.fastjson.JSON.toJSONString(productReceiveRequest);
                    String resultResp = HttpClientUtil.doPostJson(supplyApiConfig.getUrl() + "/product/getByIds", json, supplyApiConfig.getHeadsMap());
                    products = JSONObject.parseArray(resultResp, Product.class);
                }
                if(!CollectionUtils.isEmpty(products)){
                    Product product1 = products.get(0);
                    product.setBrand(product1.getBrand());
                    product.setBrandId(product1.getBrandId());
                }
                productResponse = new ProductResponse(product)
                        .setImgMapList(map).setProductRatio(ordersService.getProductRatio(product));
                redisService.set(productImgRedisKey, JSONObject.toJSONString(productImgList));
                redisService.expire(productImgRedisKey, 60);
            } else {
                List<ProductImg> productImgList = JSONArray.parseArray(redisJsonStr, ProductImg.class);
                Map<String, List<ProductImg>> map = productImgList.stream()
                        .collect(Collectors.groupingBy(ProductImg::getType));
                productResponse = new ProductResponse(product).setImgMapList(map).setProductRatio(ordersService.getProductRatio(product));;
            }

            // 普通商品
            if (product.getProductType() == 1) {
                productResponse.setActivityMax(productResponse.getOriginalPrice().subtract(productResponse.getPrice()).setScale(0, BigDecimal.ROUND_UP));
            }
            // 优惠券
            if (ActivityTypeEnums.CASH_COUPON.name().equals(product.getActivityType())) {
                productResponse.setCurPrice(product.getPrice().add(productResponse.getActivityMax()).setScale(0, BigDecimal.ROUND_UP));
            }
            productResponse.setPreferentialPrice(productResponse.getOriginalPrice().subtract(productResponse.getPrice()).setScale(0, BigDecimal.ROUND_UP));


            redisService.set(key, JSON.toJSONString(productResponse));
            redisService.expire(key, ExpireTimeConstant.PRODUCT_DETAILS_TIME);
        }
        return productResponse;
    }

    @Override
    public long queryTotalRank(Integer topCategoryId, String volumeStr,String platformData) {
//        ProductExample example = new ProductExample();
//        ProductExample.Criteria criteria = example.createCriteria();
//        if (null != topCategoryId) {
//            criteria.andTopCategoryIdEqualTo(topCategoryId);
//        }
//        criteria.andVolumeStrGreaterThan(volumeStr);
//        long topSize = productMapper.countByExample(example);
        int topSize = productMapper.countBeforeNum(topCategoryId, Integer.valueOf(volumeStr),platformData);
        return topSize + 1;
    }

    /**
     * 解析商品所属前端分类
     * @param topCategoryId 一级分类id
     * @param categoryId    二级分类id
     * @param bottomCategoryId  三级分类id
     * @return categoryName 所属前端分类名称
     */
    @Override
    public String analysisFrontCategoryName(Integer topCategoryId, Integer categoryId, Integer bottomCategoryId) {
        String redisKey = "category:front:name:" + topCategoryId + ":" + categoryId + ":" + bottomCategoryId;
        String categoryName = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(categoryName)) {
            return categoryName;
        }
        List<FrontCategory> matchAllList = frontCategoryMapper.selectByCategoryIdMatchAll(topCategoryId, categoryId, bottomCategoryId);
        if (!CollectionUtils.isEmpty(matchAllList)) {
            categoryName = matchAllList.get(0).getTitle();
            redisService.set(redisKey, categoryName);
            redisService.expire(redisKey, 2 * 60);
            return categoryName;
        }
        List<FrontCategory> matchTopCategoryList = frontCategoryMapper.selectByCategoryIdMatchTopCategoryId(topCategoryId);
        if (!CollectionUtils.isEmpty(matchTopCategoryList)) {
            categoryName = matchTopCategoryList.get(0).getTitle();
            redisService.set(redisKey, categoryName);
            redisService.expire(redisKey, 2 * 60);
            return categoryName;
        }
        return categoryName;
    }

    @Override
    public String selectProductTopCategoryName(Integer topCategoryId) {
        ProductCategory productCategory = productCategoryMapper.selectByPrimaryKey(topCategoryId);
        return null == productCategory ? "" : productCategory.getTitle();
    }


    @Override
    public Banker querySupplyChainBanker(Integer bankerId) {
        try {
            Map<String, String> param = new HashMap<>();
            param.put("bankerId", String.valueOf(bankerId));
            String result = HttpClientUtil.doGet(supplyApiConfig.getUrl() + "/banker/queryBankerById", param, supplyApiConfig.getHeadsMap());
            CommonResult commonResult = JSONObject.parseObject(result, CommonResult.class);
            if (200 != commonResult.getCode()) {
                return null;
            }
            Banker banker = JSONObject.parseObject(commonResult.getData().toString(), Banker.class);
            return banker;
        } catch (Exception e) {
            log.info("===获取供应商异常==={}", bankerId);
            log.info("==={}===", e);
        }
        return null;
    }

    @Override
    public BankerSite querySupplyChainBankerSite(Integer bankerId) {
        try {
            Map<String, String> param = new HashMap<>();
            param.put("bankerId", String.valueOf(bankerId));
            String result = HttpClientUtil.doGet(supplyApiConfig.getUrl() + "/banker/queryBankerSiteByBankerId", param, supplyApiConfig.getHeadsMap());
            CommonResult commonResult = JSONObject.parseObject(result, CommonResult.class);
            if (200 != commonResult.getCode()) {
                return null;
            }
            if (null != commonResult.getData()){
                BankerSite bankerSite = JSONObject.parseObject(commonResult.getData().toString(), BankerSite.class);
                return bankerSite;
            }
        } catch (Exception e) {
            log.info("===获取供应商店铺异常==={}", bankerId);
            log.info("==={}===", e);
        }
        return null;
    }

    @Override
    public Integer getProductBy(Integer id) {
        return productDao.getProductBy(id);
    }

    private List<ProductResponse> getRecommendOther(Integer bankerId, String activityType) {
        List<ProductResponse> productResponses = new ArrayList<>();

        if (bankerId != null) {
            String sysConfigRecommendProductIds = redisService.getMapString(RedisConstants.SYS_CONFIG, "RECOMMEND_PRODUCTIDS");
            if (StringUtils.isNotEmpty(sysConfigRecommendProductIds) && "h5".equals(TokenUtil.getSource())) {//应强哥和涛哥需要，返回指定商品的id
                productResponses = productDao.findByIds(Arrays.asList(sysConfigRecommendProductIds.split(",")));
//                productResponses = productResponses.stream().sorted((stu1, stu2) -> Long.compare(stu2.getSort(), stu1.getSort()))
//                        .collect(Collectors.toList());//按sort字段进行降序排序  强哥要求不要排序了
                if (CollectionUtils.isEmpty(productResponses)) {
                    return productResponses;
                }
                Collections.shuffle(productResponses);
                if (productResponses.size() > 12) {
                    productResponses = productResponses.subList(0, 12);
                }
            } else {
                productResponses =
                        Optional.ofNullable(productDao.getRecommendOther(bankerId, TokenUtil.getPlatformData(), activityType))
                                .orElse(new ArrayList<>());
            }

        }
        productResponses.forEach(item ->item.setWarehouseName(null));
        return productResponses;
    }

    private Integer countProductNumInBrandSite(Integer bankerId) {
        // 计算出: 品牌官网展示出的商品数量
        Integer productNumInBrandSite = 0;
        if (null != bankerId) {
            productNumInBrandSite = Optional.ofNullable(productDao.countProductNumInBrandSite(bankerId, TokenUtil.getPlatformData()))
                    .orElse(0);
        }
        return productNumInBrandSite;
    }

    @Resource
    private FakeUserUtil fakeUserUtil;

    @Override
    public ProductExtResponse queryProductExtInfo(Integer id) {
        String key = RedisConstants.PRODUCT_DETAILS + PRODUCT_DETAILS_KEY_H5 + id;
        String result = redisService.get(key);
        ProductExtResponse productResponse;
        if (result != null) {
            productResponse = com.alibaba.fastjson.JSONObject.parseObject(result, ProductExtResponse.class);
        } else {
            Product product = productMapper.selectByPrimaryKey(id);
            Optional.ofNullable(product)
                    .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
            if (product.getStatus().byteValue() != ProductStatusEnums.UP.getValue()) {
                throw new ApiException(ResultCode.NO_PRODUCT);
            }

            ProductImgExample example = new ProductImgExample();
            example.setOrderByClause("sort asc,id asc");
            example.createCriteria()
                    .andProductIdEqualTo(id);
            List<ProductImg> productImgList = productImgMapper.selectByExample(example);
            Map<String, List<ProductImg>> map = productImgList.stream()
                    .collect(Collectors.groupingBy(ProductImg::getType));
            productResponse = new ProductExtResponse(product)
                    .setImgMapList(map);
            PageButton pageButton = this.getPageButton(StringUtils.isEmpty(product.getActivityType()) ? "COMMON" : product.getActivityType());
            productResponse.setPageButton(pageButton);
            pageButton.setCopywriter(this.getCopywriter(productResponse, null));
            // 普通商品
            if (product.getProductType() == 1) {
                productResponse.setActivityMax(productResponse.getOriginalPrice().subtract(productResponse.getPrice()).setScale(0, BigDecimal.ROUND_UP));
            }
            // 优惠券
            if (ActivityTypeEnums.CASH_COUPON.name().equals(product.getActivityType())) {
                productResponse.setCurPrice(product.getPrice().add(productResponse.getActivityMax()).setScale(0, BigDecimal.ROUND_UP));
            }
            Banker banker = bankerMapper.selectByPrimaryKey(productResponse.getBankerId());
            if (banker != null) {
                productResponse.setIsHoliday(banker.getIsHoliday());
            } else {
                productResponse.setIsHoliday(0);
            }

            productResponse.setPreferentialPrice(productResponse.getOriginalPrice().subtract(productResponse.getPrice()).setScale(0, BigDecimal.ROUND_UP));
            productResponse.setUsersFakeList(fakeUserUtil.getFakeUserList());
            productResponse.setBrowseUserNum(RandomUtil.getSectionNum(6000, 8000));
            // 库存改为: 100-300的随机数
            productResponse.setStock(RandomUtil.getSectionNum(100, 300));
            redisService.set(key, JSON.toJSONString(productResponse));
            redisService.expire(key, ExpireTimeConstant.PRODUCT_DETAILS_TIME);
        }
        return productResponse;
    }

    // 字符串数组转整数集合
    private List<Integer> convertType(String config) {
        String[] str = config.split(",");
        List<Integer> ids = new ArrayList<>();
        for (int i = 0; i < str.length; i++) {
            ids.add(Integer.parseInt(str[i]));
        }

        return ids;
    }

    private RecordSubsidyDataDto insertRecordSubsidy(ProductExtResponse productResponse, String token) {
        RecordSubsidyDataDto recordSubsidyDataDto = new RecordSubsidyDataDto();

        String recordKey = RedisConstants.RECORD_SUBSIDYKEY + token;
        String recordSubsidyData = redisService.get(recordKey);
        if (null == recordSubsidyData) {
            recordSubsidyDataDto = com.alibaba.fastjson.JSONObject.parseObject(recordSubsidyData, RecordSubsidyDataDto.class);
        }

        recordSubsidyDataDto.setReceived(Optional.ofNullable(recordSubsidyDataDto.getReceived())
                .orElse(BigDecimal.ZERO)
                .add(productResponse.getActivityMax()).setScale(2, BigDecimal.ROUND_HALF_UP));

        recordSubsidyDataDto.setToken(Optional.ofNullable(recordSubsidyDataDto.getToken()).orElse(token));
        recordSubsidyDataDto.setReceiveTime(Optional.ofNullable(recordSubsidyDataDto.getReceiveTime()).orElse(new Date()));
        recordSubsidyDataDto.setUsed(Optional.ofNullable(recordSubsidyDataDto.getUsed()).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP));

        redisService.set(recordKey, JSON.toJSONString(recordSubsidyDataDto));
        redisService.expire(recordKey, ExpireTimeConstant.SUBSIDY_DATA_TIME);
        return recordSubsidyDataDto;
    }

    @Override
    public ProductResponse queryProductById(Integer id) {
        Product product = productMapper.selectByPrimaryKey(id);
        return new ProductResponse(product);
    }

    @Override
    public List<ProductResponse> getNewProductInfoList() {
        // 查询配置新品项数量
        String count = commonService.getSysConfigValue(SysConfigConstants.NEW_PRODUCT_NUMBER);
        PageHelper.startPage(1, Integer.valueOf(count));
        ProductExample example = new ProductExample();
        example.setOrderByClause("create_time desc");
        example.createCriteria()
                .andDataTypeEqualTo(TokenUtil.getDataType())
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andIsAdvertEqualTo(0)                          // 是否广告 - 0
                .andAuditStatusEqualTo(ProductAuditStatusEnums.PASS.getValue());
        List<Product> productList = productMapper.selectByExample(example);
        PageHelper.clearPage();
        return productList.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductResponse> getProductListBySpecialId(Integer id, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Product> products = productDao.queryProductListBySpecialId(id, SelectProductOrderType.COMPOSITE, null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());// 根据条件是会查出积分的,要求加以筛除
        return products.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductResponse> getProductList(String type, Integer specialId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Product> products;
        if (null == specialId) {
            ProductExample example = new ProductExample();
            switch (type) {
                case SelectProductOrderType.COMPOSITE:
                    example.setOrderByClause("sort desc");
                    break;
                case SelectProductOrderType.VOLUME:
                    example.setOrderByClause("volume desc");
                    break;
                case SelectProductOrderType.PRICE_MAX:
                    example.setOrderByClause("price desc");
                    break;
                case SelectProductOrderType.PRICE_MIN:
                    example.setOrderByClause("price asc");
                    break;
            }
            example.createCriteria()
                    .andDataTypeEqualTo(TokenUtil.getDataType())
                    .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                    .andAuditStatusEqualTo(ProductAuditStatusEnums.PASS.getValue());
            products = productMapper.selectByExample(example);
        } else {
            products = productDao.queryProductListBySpecialId(specialId, type, null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());// 根据条件是会查出积分的,要求加以筛除
        }
        return products.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
    }

    @Override
    public List<Object> getProductList(String type, Integer specialId, Integer pageNum, Integer pageSize, UsersResponse usersResponse) {
        List<Object> objectList = new ArrayList<>();
        List<Banners> bannerList = new ArrayList<>();
        if (pageNum == 1) {
            BannersExample bannersExample = new BannersExample();
            bannersExample.createCriteria()
                    .andTypeEqualTo("ad")
                    .andStatusEqualTo((byte) 1);
            bannerList = bannersMapper.selectByExample(bannersExample);
        }
        if ("v3".equals(TokenUtil.getRequest().getHeader("api-ver"))) {
            bannerList = bannerList.stream().map(item -> {
                item.setAPath(PathUtils.replaceUrl(item.getAPath()));
                return item;
            }).collect(Collectors.toList());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Product> products;
        if (null == specialId) {
            products = productDao.queryProductList(type, null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());
        } else {
            // 是否广告 - 0
            products = productDao.queryProductListBySpecialId(specialId, type, null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());// 根据条件是会查出积分的,要求加以筛除

        }
        List<ProductResponse> productResponseList = products.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
        if (pageNum == 1) {
            int j = 0;
            for (int i = 1; i <= productResponseList.size(); i++) {
                objectList.add(productResponseList.get(i - 1));
                if (i % 2 == 0) {
                    if (bannerList != null && j < bannerList.size()) {
                        objectList.add(bannerList.get(j));
                        j++;
                    }
                }
            }
        } else {
            objectList.addAll(productResponseList);
        }
        return objectList;
    }

    @Override
    public List<Object> getProductListNew(ProductListRequest request) {
        List<Object> objectList = new ArrayList<>();
        List<Banners> bannerList = new ArrayList<>();
        if (request.getPageNum() == 1) {
            BannersExample bannersExample = new BannersExample();
            bannersExample.createCriteria()
                    .andTypeEqualTo("ad")
                    .andStatusEqualTo((byte) 1);
            bannerList = bannersMapper.selectByExample(bannersExample);
        }
        if ("v3".equals(TokenUtil.getRequest().getHeader("api-ver"))) {
            bannerList = bannerList.stream().map(item -> {
                item.setAPath(PathUtils.replaceUrl(item.getAPath()));
                return item;
            }).collect(Collectors.toList());
        }
//        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<Product> products;
        if (null == request.getSpecialId()) {
            products = productDao.queryProductList(request.getType(), null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());
        } else {
            if (redisService.get("categoryIdsProducts:" + request.getType() + ":" + request.getSpecialId()) == null){
                products = getGraduateProductList(request.getSpecialId(), request.getType(), TokenUtil.getDataType(), TokenUtil.getPlatformData());// 根据条件是会查出积分的,要求加以筛除
            }else {
                String s = redisService.get("categoryIdsProducts:" + request.getType() + ":" + request.getSpecialId());
                String[] split = s.split(",");
                List<Integer> id = new ArrayList<>();
                for (String s1 : split) {
                    if (StringUtils.isNotEmpty(s1)) {
                        id.add(Integer.valueOf(s1));
                    }
                }
                Integer Num = (request.getPageNum() - 1) * 10;
                products = productDao.selectByIdsOrderByType(id, Num, request.getType());
            }
        }
        List<ProductResponse> productResponseList = products.stream()
                .limit(10)
                .map(ProductResponse::new)
                .collect(Collectors.toList());
        if (request.getPageNum() == 1) {
            int j = 0;
            for (int i = 1; i <= productResponseList.size(); i++) {
                objectList.add(productResponseList.get(i - 1));
                if (i % 2 == 0) {
                    if (bannerList != null && j < bannerList.size()) {
                        objectList.add(bannerList.get(j));
                        j++;
                    }
                }
            }
        } else {
            objectList.addAll(productResponseList);
        }
        return objectList;
    }


    @Override
    public List<Object> getProductListNewFixPrice(ProductListRequest request) {
        List<Object> objectList = new ArrayList<>();
        List<Banners> bannerList = new ArrayList<>();
        if (request.getPageNum() == 1) {
            BannersExample bannersExample = new BannersExample();
            bannersExample.createCriteria()
                    .andTypeEqualTo("ad")
                    .andStatusEqualTo((byte) 1);
            bannerList = bannersMapper.selectByExample(bannersExample);
        }
        if ("v3".equals(TokenUtil.getRequest().getHeader("api-ver"))) {
            bannerList = bannerList.stream().map(item -> {
                item.setAPath(PathUtils.replaceUrl(item.getAPath()));
                return item;
            }).collect(Collectors.toList());
        }
//        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        BigDecimal fixPrice = new BigDecimal(fixPriceParam);
        List<Product> products = new ArrayList<>();
        if (null == request.getSpecialId()) {
            products = productDao.queryProductListFixPrice(request.getType(), null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData(), fixPrice);
        } else {
            if (redisService.get("categoryIdsFixPriceProducts:" + request.getType() + ":" + request.getSpecialId()) == null){
                products = getGraduateProductListFixPrice(request.getSpecialId(), request.getType(), TokenUtil.getDataType(), TokenUtil.getPlatformData(), fixPrice);// 根据条件是会查出积分的,要求加以筛除
            }else {
                String s = redisService.get("categoryIdsFixPriceProducts:" + request.getType() + ":" + request.getSpecialId());
                String[] split = s.split(",");
                List<Integer> id = new ArrayList<>();
                for (String s1 : split) {
                    if (StringUtils.isNotEmpty(s1)) {
                        id.add(Integer.valueOf(s1));
                    }
                }
                Integer Num = (request.getPageNum() - 1) * 10;
                if (!CollectionUtils.isEmpty(id)){
                    products = productDao.selectByIdsOrderByTypeFixPrice(id, Num, request.getType(), fixPrice);
                }
            }
        }
        List<ProductResponse> productResponseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(products)){
             productResponseList = products.stream()
                    .limit(10)
                    .map(ProductResponse::new)
                    .collect(Collectors.toList());
        }

        if (request.getPageNum() == 1 ) {
            int j = 0;
            for (int i = 1; i <= productResponseList.size(); i++) {
                objectList.add(productResponseList.get(i - 1));
                if (i % 2 == 0) {
                    if (bannerList != null && j < bannerList.size()) {
                        objectList.add(bannerList.get(j));
                        j++;
                    }
                }
            }
        } else {
            objectList.addAll(productResponseList);
        }
        return objectList;
    }

    @Override
    public Map<String, Object> getCorrelationProduct(Integer specialId, Integer productId) {
        if (null == specialId) {
            // 专区为空，查询商品所属专区
            ProductSpecialExample example = new ProductSpecialExample();
            example.createCriteria()
                    .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                    .andProductIdEqualTo(productId);
            List<ProductSpecial> list = productSpecialMapper.selectByExample(example);
            if (list.size() > 0) {
                specialId = list.get(0).getSpecialId();
            }
        }
        PageHelper.startPage(1, 7);
        List<Product> products = productDao.queryProductListBySpecialId(specialId, SelectProductOrderType.VOLUME, null, null, TokenUtil.getDataType(), TokenUtil.getPlatformData());
        products = products.stream()
                .filter(product -> !product.getId().equals(productId))
                .limit(6)
                .collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("specialId", specialId);
        map.put("productList", products.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList()));
        return map;
    }

    @Override
    public ProductSpecResponse getProductSpecInfo(Integer productId, String productSpec) {
        Optional.ofNullable(productMapper.selectByPrimaryKey(productId))
                .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
        ProductSpecExample example = new ProductSpecExample();
        example.createCriteria()
                .andProductIdEqualTo(productId)
                .andSkuSpecEqualTo(productSpec);
        List<ProductSpec> productSpecList = Optional.ofNullable(productSpecMapper.selectByExample(example))
                .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_STOCK)));
        if (productSpecList.size() <= 0) {
            throw new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_STOCK));
        }
        return new ProductSpecResponse(productSpecList.get(0));
    }

    @Override
    public ProductSpecResponse getProductSpecInfoById(Integer specId) {
        ProductSpec productSpec = productSpecMapper.selectByPrimaryKey(specId);
        Optional.ofNullable(productSpec)
                .orElseThrow(() -> new ApiException("该商品规格不存在!"));
        return new ProductSpecResponse(productSpec);
    }

    @Override
    public ProductSpec getProductSpecById(Integer specId) {
        ProductSpec productSpec = productSpecMapper.selectByPrimaryKey(specId);
        Optional.ofNullable(productSpec)
                .orElseThrow(() -> new ApiException("该商品规格不存在!"));
        return productSpec;
    }


    /**
     * 获取专区的新品推荐和广告图
     *
     * @return
     */
    @Override
    public Map<String, Object> getNewProductsAndBanner(Integer specialId) {
        Map<String, Object> result = new HashMap<>();
        SpecialBannerEnums bannerType = SpecialBannerEnums.getSpecialBannerEnums(specialId);
        // 广告列表
        BannersExample bannersExample = new BannersExample();
        bannersExample.createCriteria()
                .andTypeEqualTo(bannerType.toString())
                .andStatusEqualTo((byte) 1);
        List<Banners> banners = bannersMapper.selectByExample(bannersExample);
        // 新品推荐
        ProductExample example = new ProductExample();
        example.setOrderByClause("create_time desc");
        example.createCriteria()
                .andDataTypeEqualTo(TokenUtil.getDataType())
                .andSpecialIdEqualTo(specialId)
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andIsAdvertEqualTo(0)                          // 是否广告 - 0
                .andIsHideEqualTo(0)
                .andBankerColumnIdEqualTo(2)//品质好货
                .andActivityTypeNotIn(Arrays.asList(ActivityTypeEnums.GET_SCORE.name()
                        , ActivityTypeEnums.CASH_COUPON.name()
                        , ActivityTypeEnums.RECHARGE_COUPON.name()));
        List<Product> products = productMapper.selectByExample(example);

        List<ProductResponse> productResponseList = products.stream()
                .limit(6)
                .map(ProductResponse::new)
                .collect(Collectors.toList());
        result.put("banners", banners);
        result.put("newProducts", productResponseList);
        return result;
    }

    @Override
    public Map<String, Object> getNewProductsAndBannerNew(Integer specialId) {
        Map<String, Object> result = new HashMap<>();
        SpecialBannerEnums bannerType = SpecialBannerEnums.getSpecialBannerEnums(specialId);
        // 广告列表
//        BannersExample bannersExample = new BannersExample();
//        bannersExample.createCriteria()
//                .andTypeEqualTo(bannerType.toString())
//                .andStatusEqualTo((byte) 1);
//        List<Banners> banners = bannersMapper.selectByExample(bannersExample);
        List<Banners> banners = bannersMapper.selectBySpecialId(specialId);
        for (Banners banner : banners) {
            banner.setImgUrl(banner.getImage());
        }
        // 新品推荐
        //活动类型
        List<String> activityTypeList = Arrays.asList(ActivityTypeEnums.GET_SCORE.name()
                , ActivityTypeEnums.CASH_COUPON.name()
                , ActivityTypeEnums.RECHARGE_COUPON.name());
        List<Product> products = new ArrayList<>();
        if (redisService.get("specialId-productList"+ ":" + specialId) == null){
            products = getProductBySpecialId(specialId, TokenUtil.getDataType(), activityTypeList);
        }else {
            String s = redisService.get("specialId-productList"+ ":" + specialId);
            String[] split = s.split(",");
            List<Integer> id = new ArrayList<>();
            for (String s1 : split) {
                if (StringUtils.isNotEmpty(s1)) {
                    id.add(Integer.valueOf(s1));
                }
            }
            products = productDao.selectByIds(id , 0);
        }
        List<ProductResponse> productResponseList = products.stream()
                .limit(6)
                .map(ProductResponse::new)
                .collect(Collectors.toList());
        result.put("banners", banners);
        result.put("newProducts", productResponseList);
        return result;
    }

    /**
    * 好物推荐
    * @param request:
    * @returns: java.util.Map<java.lang.String,java.lang.Object>
    * 
    */
    @Override
    public List<Product> getNewProductsAndBannerNewWay2(ProductListRequest request) {
        // 新品推荐
        //活动类型
        List<String> activityTypeList = Arrays.asList(ActivityTypeEnums.GET_SCORE.name()
                , ActivityTypeEnums.CASH_COUPON.name()
                , ActivityTypeEnums.RECHARGE_COUPON.name());
        List<Product> products = new ArrayList<>();
        if (redisService.get("recommendProductsOfSpecial"+ ":" + request.getSpecialId()) == null){
            products = frontCategoryService.getRecommendProductListByFrontId(request.getSpecialId(),
                    TokenUtil.getDataType(), activityTypeList,request.getPageNum(),request.getPageSize(), TokenUtil.getPlatformData());
        }else {
            String s = redisService.get("recommendProductsOfSpecial"+ ":" + request.getSpecialId());
            String[] split = s.split(",");
            if (split.length <= 0) {
                return products;
            }
            List<Integer> id = new ArrayList<>();
            for (String s1 : split) {
                if (StringUtils.isNotEmpty(s1)) {
                    id.add(Integer.valueOf(s1));
                }
            }
            if (CollectionUtils.isEmpty(id)) {
                return products;
            }
            Integer num = (request.getPageNum() - 1) * 10;
            products = productDao.selectByIds(id , num);
        }
        products.stream().forEach(item ->{
            item.setPrice(item.getPrice().setScale(0,BigDecimal.ROUND_DOWN));
            item.setOriginalPrice(item.getOriginalPrice().setScale(0,BigDecimal.ROUND_DOWN));
            String headImgStr = redisService.get(RedisConstants.BUY_PRODUCT_USER_HEAD_IMG + item.getId());
            if (StringUtils.isNotBlank(headImgStr)) {
                List<String> list = JSONObject.parseArray(headImgStr, String.class);
                item.setHeadImgs(list);
            } else {
//                List<Integer> userIds = ordersDao.selectByProductId(item.getId());
//                List<String> headImgs = usersInfoMapper.selectHeadImgsByUserId(userIds);
                List<String> headImgs = usersInfoMapper.selectHeadImgs();
                String s = JSONObject.toJSONString(headImgs);
                redisService.set(RedisConstants.BUY_PRODUCT_USER_HEAD_IMG + item.getId(), s);
                redisService.expire(RedisConstants.BUY_PRODUCT_USER_HEAD_IMG + item.getId(), 60 * 60);
                item.setHeadImgs(headImgs);
            }
        });
        return products;
    }

    /**
     * 通过专区找商品
     *
     * @param specialId
     * @param dataType
     * @param activityTypeList
     * @return
     */
    private List<Product> getProductBySpecialId(Integer specialId, String dataType, List<String> activityTypeList) {
        //通过专区id找专区信息
        Special special = specialMapper.selectByPrimaryKey(specialId);
        //获取分类id
        String categoryListStr = special.getCategoryListStr();
        if (org.springframework.util.StringUtils.isEmpty(categoryListStr)) {
            return null;
        }
        String[] split = categoryListStr.split(",");
        List<Integer> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Integer.valueOf(s));
        }
        //通过专区里的分类id获取到分类对象集合
        List<ProductCategoryResp> list = productDao.selectCategoryByIds(ids);
        //分类集合进行排序(三级放二级,二级放一级里)
        List<ProductCategoryResp> productCategoryResp = getProductCategoryResps(list);
        if (1 == special.getCategoryType()) {//专区类目类型为一级类目
            //获取所有的一级类目id
            List<Integer> topCategoryIds = new ArrayList<>();
            productCategoryResp.forEach(topCategory -> {
                topCategoryIds.add(topCategory.getId());
            });
            //根据一级分类id查商品
            List<Product> productList = productDao.selectProductByTopCategory(topCategoryIds, dataType, activityTypeList);
            String id = "";
            for (Product product : productList) {
                id = id + "," + product.getId() ;
            }
            redisService.set("specialId-productList"+ ":" + specialId,id);
            redisService.expire("specialId-productList"+ ":" + specialId,10*60);
            return productList;
        } else {//专区类目类型为自定义类目
            List<Integer> categoryIds = getCategoryIds(productCategoryResp);
            //
            List<Product> productList = productDao.selectProductByCategorys(categoryIds, dataType, activityTypeList);
            String id = "";
            for (Product product : productList) {
                id = id + "," + product.getId() ;
            }
            redisService.set("specialId-productList"+ ":" + specialId,id);
            redisService.expire("specialId-productList"+ ":" + specialId,10*60);
            return productList;
        }
    }

    /**
     *  分类集合--例如-"[[1,2,3],[1,2,4],[5,6],[7]]"获取该集合里的集合中最后一个元素
     * @param productCategoryResp
     * @return
     */
    public List<Integer> getCategoryIds(List<ProductCategoryResp> productCategoryResp) {
        List<List<Integer>> categoryIdsList = new ArrayList<>();//分类集合--例如-"[[1,2,3],[1,2,4],[5,6],[7]]"
        productCategoryResp.forEach(category -> {
            List<ProductCategoryResp> childProductCategory = category.getChildProductCategory();
            if (!CollectionUtils.isEmpty(childProductCategory)) {
                childProductCategory.forEach(twoCategory -> {
                    List<ProductCategoryResp> bottomProductCategory = twoCategory.getChildProductCategory();
                    if (!CollectionUtils.isEmpty(bottomProductCategory)) {
                        bottomProductCategory.forEach(bottomCategory -> {
                            List<Integer> categoryIds = new ArrayList<>();
                            categoryIds.add(category.getId());
                            categoryIds.add(twoCategory.getId());
                            categoryIds.add(bottomCategory.getId());
                            categoryIdsList.add(categoryIds);
                        });
                    } else {
                        List<Integer> categoryIds = new ArrayList<>();
                        categoryIds.add(category.getId());
                        categoryIds.add(twoCategory.getId());
                        categoryIdsList.add(categoryIds);
                    }
                });
            } else {
                List<Integer> categoryIds = new ArrayList<>();
                categoryIds.add(category.getId());
                categoryIdsList.add(categoryIds);
            }
        });
        //获取categoryList里每个集合的最后一个索引作集合
        List<Integer> categoryIds = new ArrayList<>();
        categoryIdsList.forEach(categoryIdList -> {
            categoryIds.add(categoryIdList.get(categoryIdList.size() - 1));
        });
        return categoryIds;
    }

    @Resource
    private UsersClient usersClient;

    @Override
    public void sellAfter(Integer productId, Integer productSpecId, Integer sum, BigDecimal productPrice, Integer isWalletPay, String tokenUsers,
                          Integer isDirectbuy, String activityType, BigDecimal activityMax, Integer userId) {
        SellAfterDto sellAfterDto = new SellAfterDto(productId, productSpecId, sum, productPrice, isWalletPay, tokenUsers, isDirectbuy, activityType, activityMax, userId);
        rabbitTemplate.convertAndSend(QueueConstants.SELL_AFTER_QUEUE_ONE, sellAfterDto);
    }

    /**
     * 商品回调 减库存 加销量
     *
     * @param productId
     * @param productSpecId
     * @param sum
     * @param productPrice
     * @param isWalletPay
     * @param tokenUsers
     * @param isDirectbuy
     * @param activityType
     * @param activityMax
     * @param userId
     */
    @Override
    @Transactional
    public void sellAfterOld(Integer productId, Integer productSpecId, Integer sum, BigDecimal productPrice, Integer isWalletPay, String tokenUsers,
                             Integer isDirectbuy, String activityType, BigDecimal activityMax, Integer userId) {

        UsersResponse token = JSONObject.parseObject(tokenUsers, UsersResponse.class);
        if (null != token) {
            if (isWalletPay == 1) {
                token.setMoney(new BigDecimal(0));
            }
        }

        // 减库存 加销量
//        Product product = productMapper.selectByPrimaryKey(productId);
//        if (product.getIsZeroProduct() != null && product.getIsZeroProduct() == 1 && product.getStockEvaluation() != null && product.getStockEvaluation() > 0) {
//            product.setStockEvaluation(product.getStockEvaluation() - sum);
//        } else {
//            product.setStock(Optional.ofNullable(product.getStock()).orElse(0) - sum);
//        }
//
//        product.setVolume(product.getVolume() + sum);
//        productMapper.updateByPrimaryKeySelective(product);
//        ProductSpec productSpec = productSpecMapper.selectByPrimaryKey(productSpecId);
////        productSpec.setBuySum(productSpec.getBuySum() + sum);
//        productSpec.setStock(Optional.ofNullable(productSpec.getStock()).orElse(0) - sum);
//        productSpecMapper.updateByPrimaryKeySelective(productSpec);
        // 加店家销量
//        Banker banker = bankerMapper.selectByPrimaryKey(product.getBankerId());
//        Map<String, String> param = new HashMap<>();
//        param.put("bankerId", String.valueOf(product.getBankerId()));
//        String resultJson = HttpClientUtil.doGet(supplyApiConfig.getUrl() + "/banker/queryBankerById", param, supplyApiConfig.getHeadsMap());
//        if (banker != null) {
//            banker.setSales(Optional.ofNullable(banker.getSales()).orElse(0) + sum);
//            banker.setSalesMoney(Optional.ofNullable(banker.getSalesMoney()).orElse(new BigDecimal(0)).add(productPrice).setScale(2));
//            bankerMapper.updateByPrimaryKeySelective(banker);
//        }

        UsersResponse usersResponse = usersClient.getUsers(userId);
//        boolean key = null != usersResponse && usersResponse.getStatus().byteValue() == (byte) 3;

        boolean key = null != usersResponse && usersResponse.getStatus().byteValue() == (byte) 1;
        log.info("===usersId:{}, key:{}===", userId, key);
        // 直接购买不做任何操作
        if (isDirectbuy == 0) {
            // 根据活动类型做不同策略
            switch (activityType) {
                case "CASH_SCORE":
                    token.setScore(token.getScore() - activityMax.intValue() <= 0 ? 0 : token.getScore() - activityMax.intValue());
//                    if (key) {
//                        usersClient.subScore(Optional.ofNullable(activityMax).orElse(BigDecimal.ZERO).intValue(), userId, activityType);
//                    }
                    break;
                case "GET_SCORE":
                case "NEW_USER":
                    // 新人首单的加积分 加积分流水
                    // 返现积分的加积分 加积分流水
                    // token.setScore(token.getScore() + activityMax.intValue());
                    token.setTaskScore(token.getTaskScore() + activityMax.intValue());
                    if (key) {
                        usersClient.addScore(activityMax.intValue(), userId, activityType);
                    }
                    break;
                case "RETURN_CASH":
                    // 钱包返现 加金额
                    token.setMoney(token.getMoney().add(activityMax).setScale(2));
                    if (key) {
                        usersClient.addBalance(activityMax, userId, activityType);
                    }
                    break;
            }
        }
        log.info("处理完购买用户信息 : {}", JSONObject.toJSONString(token));
        redisService.set(token.getToken(), JSONObject.toJSONString(token));
        redisService.expire(token.getToken(), TokenConstants.EXPIRE_SECONDS);

    }

    @Override
    public void sellAfter(Integer productId, Integer productSpecId, Integer sum, BigDecimal productPrice,
                          Integer isWalletPay, Integer isDirectbuy, String activityType, BigDecimal activityMax, Integer userId) {
        SellAfterDto sellAfterDto = new SellAfterDto(productId, productSpecId, sum, productPrice, isWalletPay, isDirectbuy, activityType, activityMax, userId);
        rabbitTemplate.convertAndSend(QueueConstants.SELL_AFTER_QUEUE, sellAfterDto);
    }

    @Override
    @Transactional
    public void sellAfterOld(Integer productId, Integer productSpecId, Integer sum, BigDecimal productPrice,
                             Integer isWalletPay, Integer isDirectbuy, String activityType, BigDecimal activityMax, Integer userId) {
        // 减库存 加销量
        Product product = productMapper.selectByPrimaryKey(productId);
//        if (product.getIsZeroProduct() != null && product.getIsZeroProduct() == 1 && product.getStockEvaluation() != null && product.getStockEvaluation() > 0) {
//            product.setStockEvaluation(product.getStockEvaluation() - sum);
//        } else {
//            product.setStock(Optional.ofNullable(product.getStock()).orElse(0) - sum);
//        }
//        productMapper.updateByPrimaryKeySelective(product);
//        ProductSpec productSpec = productSpecMapper.selectByPrimaryKey(productSpecId);
//        productSpec.setBuySum(Optional.ofNullable(productSpec.getBuySum()).orElse(0) + sum);
//        productSpec.setStock(Optional.ofNullable(productSpec.getStock()).orElse(0) - sum);
//        productSpecMapper.updateByPrimaryKeySelective(productSpec);
        // 加店家销量
//        Banker banker = bankerMapper.selectByPrimaryKey(product.getBankerId());
//        if (banker != null) {
//            banker.setSales(Optional.ofNullable(banker.getSales()).orElse(0) + sum);
//            banker.setSalesMoney(Optional.ofNullable(banker.getSalesMoney()).orElse(BigDecimal.valueOf(0)).add(productPrice).setScale(2));
//            bankerMapper.updateByPrimaryKeySelective(banker);
//        }
        // 直接购买不做任何操作
        if (isDirectbuy == 0) {
            // 根据活动类型做不同策略
            switch (activityType) {
                case "CASH_SCORE":
                    // 兑换积分的扣积分 加扣积分流水
                    usersClient.subScore(activityMax.intValue(), userId, activityType);
                    break;
                case "GET_SCORE":
                case "NEW_USER":
                    // 新人首单的加积分 加积分流水
                    // 返现积分的加积分 加积分流水
                    usersClient.addScore(activityMax.intValue(), userId, activityType);
                    break;
                case "RETURN_CASH":
                    // 钱包返现 加金额
                    usersClient.addBalance(activityMax, userId, activityType);
                    break;
            }
        }

    }

    @Override
    public List<ProductResponse> getGraduateProductList(Integer specialId, String type) {
        List<Product> productList = productDao.queryGraduateProductListByType(specialId, type);
        return productList.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
    }

    /**
     * 通过专区id找商品(new)
     *
     * @param specialId
     * @return
     */
    public List<Product> getGraduateProductList(Integer specialId,
                                                String type,
                                                String dataType,
                                                String platformData) {
        //通过专区id找专区信息
        Special special = specialMapper.selectByPrimaryKey(specialId);
        //获取分类id
        String categoryListStr = special.getCategoryListStr();
        if (org.springframework.util.StringUtils.isEmpty(categoryListStr)) {
            return null;
        }
        String[] split = categoryListStr.split(",");
         List<Integer> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Integer.valueOf(s));
        }
        //通过专区里的分类id获取到分类对象集合
        List<ProductCategoryResp> list = productDao.selectCategoryByIds(ids);
        //分类集合进行排序(三级放二级,二级放一级里)
        List<ProductCategoryResp> productCategoryResp = getProductCategoryResps(list);
        if (1 == special.getCategoryType()) {//专区类目类型为一级类目
            //获取所有的一级类目id
            List<Integer> topCategoryIds = new ArrayList<>();
            productCategoryResp.forEach(topCategory -> {
                topCategoryIds.add(topCategory.getId());
            });
            //根据一级分类id查商品
            List<Product> productList = productDao.selectProductByTopCategoryIds(topCategoryIds, type, dataType, platformData);
            String id = "";
            for (Product product : productList) {
                id = id + "," + product.getId() ;
            }
            redisService.set("categoryIdsProducts:" + type + ":" + specialId,id);
            redisService.expire("categoryIdsProducts:" + type + ":" + specialId,10 * 60);
            return productList;
        } else {//专区类目类型为自定义类目
            List<Integer> categoryIds = getCategoryIds(productCategoryResp);
            //
            List<Product> productList = productDao.selectProductByCategoryIds(categoryIds, type, dataType, platformData);
            String id = "";
            for (Product product : productList) {
                id = id + "," + product.getId() ;
            }
            redisService.set("categoryIdsProducts:" + type + ":" + specialId, id);
            redisService.expire("categoryIdsProducts:" + type + ":" + specialId,10 * 60);
            return productList;
        }
    }

    /**
     * 通过专区id找商品(new)
     * @param specialId
     * @return
     */
    public List<Product> getGraduateProductListFixPrice(Integer specialId,
                                                String type,
                                                String dataType,
                                                String platformData, BigDecimal fixPrice) {
        //通过专区id找专区信息
        FrontCategory frontCategory = frontCategoryMapper.selectByPrimaryKey(specialId);
        //获取分类id
        String categoryListStr = frontCategory.getCategoryList();
        if (org.springframework.util.StringUtils.isEmpty(categoryListStr)) {
            return null;
        }
        String[] split = categoryListStr.split(",");
        List<Integer> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Integer.valueOf(s));
        }
        //通过专区里的分类id获取到分类对象集合
        List<ProductCategoryResp> list = productDao.selectCategoryByIds(ids);
        //分类集合进行排序(三级放二级,二级放一级里)
        List<ProductCategoryResp> productCategoryResp = getProductCategoryResps(list);
        //获得层级关系的最后一级id
        List<Integer> categoryIds = getCategoryIds(productCategoryResp);
        List<Product> productList = productDao.selectProductByCategoryIdsFixPrice(categoryIds, type, dataType, platformData, fixPrice);
        String id = "";
        for (Product product : productList) {
            id = id + "," + product.getId();
        }
        redisService.set("categoryIdsFixPriceProducts:" + type + ":" + specialId, id);
        redisService.expire("categoryIdsFixPriceProducts:" + type + ":" + specialId, 10 * 60);
        return productList;

    }

    /**
     * 通过专区找商品
     *
     * @return
     */
    public List<Product> getProductBySpecialId(Integer specialId,
                                               String type,
                                               String dataType,
                                               String platformData) {
        //通过专区id找专区信息
        Special special = specialMapper.selectByPrimaryKey(specialId);
        //获取分类id
        String categoryListStr = special.getCategoryListStr();
        if (org.springframework.util.StringUtils.isEmpty(categoryListStr)) {
            return null;
        }
        String[] split = categoryListStr.split(",");
        List<Integer> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Integer.valueOf(s));
        }
        //通过专区里的分类id获取到分类对象集合
        List<ProductCategoryResp> list = productDao.selectCategoryByIds(ids);
        //分类集合进行排序(三级放二级,二级放一级里)
        List<ProductCategoryResp> productCategoryResp = getProductCategoryResps(list);
        if (1 == special.getCategoryType()) {//专区类目类型为一级类目
            //获取所有的一级类目id
            List<Integer> topCategoryIds = new ArrayList<>();
            productCategoryResp.forEach(topCategory -> {
                topCategoryIds.add(topCategory.getId());
            });
            //根据一级分类id查商品
            List<Product> productList = productDao.selectProductByTopCategoryIds(topCategoryIds, type, dataType, platformData);
            return productList;
        } else {//专区类目类型为自定义类目
            List<Integer> categoryIds = getCategoryIds(productCategoryResp);
            //
            List<Product> productList = productDao.selectProductByCategoryIds(categoryIds, type, dataType, platformData);
            return productList;
        }
    }

    /**
     * //分类集合进行排序(三级放二级,二级放一级里)
     *
     * @param categoryList
     * @return
     */
    public List<ProductCategoryResp> getProductCategoryResps(List<ProductCategoryResp> categoryList) {
        List<ProductCategoryResp> categoryDTOList = new ArrayList<>();
        //查询所有父类目录
        for (ProductCategoryResp categoryEntity : categoryList) {
            if (categoryEntity.getPid() == 0) {
                categoryDTOList.add(categoryEntity);
            }
        }
        //查询子目录
        findSubCategory(categoryDTOList, categoryList);

        return categoryDTOList;
    }

    /**
     * 查询子目录
     *
     * @param categoryDTOList 根目录
     * @param categoryEntityList
     */
    private void findSubCategory(List<ProductCategoryResp> categoryDTOList, List<ProductCategoryResp> categoryEntityList) {
        //遍历所有父类分类
        for (ProductCategoryResp categoryDTO : categoryDTOList) {
            List<ProductCategoryResp> subCategoryVoList = new ArrayList<>();
            //遍历父类下的cat_id与子类parent_cid相匹配的分类
            for (ProductCategoryResp category : categoryEntityList) {
                if (categoryDTO.getId().equals(category.getPid())) {
                    subCategoryVoList.add(category);
                }
                //设置subCategories
                categoryDTO.setChildProductCategory(subCategoryVoList);
            }
            //递归调用
            findSubCategory(subCategoryVoList, categoryEntityList);
        }
    }

    @Override
    public List<ProductSpecResponse> getProductSpecList(Integer productId) {
        ProductSpecExample example = new ProductSpecExample();
        example.createCriteria()
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andProductIdEqualTo(productId);
        List<ProductSpec> productSpecList = productSpecMapper.selectByExample(example);
        List<ProductSpecVO> specVOList = querySupplyProductSpecStock(productId);
//        log.info("===specVOList==={}", specVOList);
        if (!CollectionUtils.isEmpty(specVOList)) {
            productSpecList.stream().forEach(item -> {
//                log.info("===item==={}", item);
                specVOList.stream().forEach(specVO -> {
                    if (item.getSupplyId().equals(specVO.getId())) {
                        item.setStock(specVO.getStock());
                    }
                });
            });
        }
        return productSpecList.stream().map(ProductSpecResponse::new)
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductSpecResponse> getProductsSpecList(List<Product> productList) {
        List<Integer> productIds = productList.stream().map(Product::getId).collect(Collectors.toList());
        List<Integer> bankerProductIds = productList.stream().map(Product::getBankerProductId).collect(Collectors.toList());
        ProductSpecExample example = new ProductSpecExample();
        example.createCriteria()
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andProductIdIn(productIds);
        List<ProductSpec> productSpecList = productSpecMapper.selectByExample(example);
//        log.info("productSpecList:{}",JSONObject.toJSON(productSpecList));
        List<ProductSpecVO> specVOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(bankerProductIds)) {
            String bankerProductIdStr =  StringUtils.join(bankerProductIds,",");
            Map<String, String> map = new LinkedMap();
            map.put("bankerProductIds", bankerProductIdStr);
//            log.info("===map==={}", JSONObject.toJSONString(map));
            String resultJson = HttpClientUtil.doGet(supplyApiConfig.getUrl() + "/stock/querySupplyProductStockByBankerProductId", map, supplyApiConfig.getHeadsMap());
            CommonResult commonResult = com.alibaba.fastjson.JSONObject.parseObject(resultJson, CommonResult.class);
            if (commonResult==null) {
                return null;
            }
            List<SupplyChainProductSpecStockResponse> responses = JSONArray.parseArray(commonResult.getData().toString(), SupplyChainProductSpecStockResponse.class);
            if (!CollectionUtils.isEmpty(responses)) {
                responses.forEach(response -> {
                    if (!CollectionUtils.isEmpty(response.getProductSpecList())) {
                        specVOList.addAll(response.getProductSpecList());
                    }
                } );
            }
        }
        if (!CollectionUtils.isEmpty(specVOList)) {
            productSpecList.stream().forEach(item -> {
//                log.info("===item==={}", item);
                specVOList.stream().forEach(specVO -> {
                    if (item.getSupplyId().equals(specVO.getId())) {
                        item.setStock(specVO.getStock());
                    }
                });
            });
        }
        return productSpecList.stream().map(ProductSpecResponse::new)
                .collect(Collectors.toList());
    }

    /**
     * 根据供应商商品id查询供应链商品库存
     * @param productId
     * @return List<ProductSpecVO>
     */
    private List<ProductSpecVO> querySupplyProductSpecStock(Integer productId) {
        Product product = productMapper.selectByPrimaryKey(productId);
        Map<String, String> map = new LinkedMap();
        map.put("bankerProductIds", String.valueOf(product.getBankerProductId()));
//        log.info("===map==={}", JSONObject.toJSONString(map));
        String resultJson = HttpClientUtil.doGet(supplyApiConfig.getUrl() + "/stock/querySupplyProductStockByBankerProductId", map, supplyApiConfig.getHeadsMap());

        CommonResult commonResult = com.alibaba.fastjson.JSONObject.parseObject(resultJson, CommonResult.class);
//        log.info("===commonResult==={}", JSONObject.toJSONString(commonResult));
        if (200 != commonResult.getCode()) {
            return null;
        }
        List<SupplyChainProductSpecStockResponse> responses = JSONArray.parseArray(commonResult.getData().toString(), SupplyChainProductSpecStockResponse.class);
//        log.info("===responses==={}", JSONObject.toJSONString(responses));
        if (CollectionUtils.isEmpty(responses)) {
            return null;
        }
        SupplyChainProductSpecStockResponse stockResponse = responses.get(0);
        if (null == stockResponse) {
            return null;
        }
        if (!product.getBankerProductId().equals(stockResponse.getBankerProductId())) {
            return null;
        }
        List<ProductSpecVO> specVOList = stockResponse.getProductSpecList();
//        List<ProductSpecVO> specVOList = JSONArray.parseArray(stockResponse.getProductSpecList().toString(), ProductSpecVO.class);
        return specVOList;
    }

    /**
     * 获取商品规格
     *
     * @param id
     * @param isActivity
     * @return
     */
    public List<RecommendProductSpecResponse> getRecommendProductSpecList(Integer id, Integer isActivity) {
        if (IsActivityConstant.NO.equals(isActivity)) {
            ProductSpecExample example = new ProductSpecExample();
            example.createCriteria()
                    .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                    .andProductIdEqualTo(id);
            List<ProductSpec> productSpecList = productSpecMapper.selectByExample(example);
            return productSpecList.stream().map(item -> new RecommendProductSpecResponse(item))
                    .collect(Collectors.toList());
        } else {
            ProductActivitySpecExample example = new ProductActivitySpecExample();
            example.createCriteria()
                    .andActivityIdEqualTo(id);
            List<ProductActivitySpec> productSpecList = productActivitySpecMapper.selectByExample(example);
            return productSpecList.stream().map(item -> new RecommendProductSpecResponse(item))
                    .collect(Collectors.toList());
        }
    }

    @Override
    public Integer getProductStatusByProductId(Integer productId) {
        Product product = productMapper.selectByPrimaryKey(productId);
        return Integer.valueOf(product.getStatus());
    }

    @Autowired
    private SysConfigUtil sysConfigUtil;

    /**
     * 根据年龄段查找商品
     *
     * @param productId
     * @param ageStr
     * @param dataType
     * @param pageNum
     * @param pageSize
     * @param activityType
     * @return
     */
    public List<ProductEsDto> getProductByAge(Integer productId, String ageStr, String dataType, Integer pageNum, Integer pageSize, String activityType) {

        BoolQueryBuilder query = new MyBoolQueryBuilder(pageNum - 1, pageSize);
        if (StringUtils.isNotEmpty(ageStr)) {
            query.must(multiMatchQuery(ageStr, "age_str"));
//            BoolQueryBuilder queryBuilder = boolQuery();
//            String[] split = ageStr.split(",");
//            for (String filed : split) {
//                queryBuilder.should(wildcardQuery("age_str", "*" + filed + "*"));
//            }
//            query.must(queryBuilder);
        }

        query.must(termQuery("status", 1));
//        query.must(termQuery("data_type", dataType));
//        query.must(termQuery("product_type", 1));
        query.must(termQuery("banker_column_id", 2));
//        query.must(termQuery("audit_status", 1));
        query.must(termQuery("rec_img_flag", 1));
        if (StringUtils.isNotEmpty(activityType)) {
            query.must(matchQuery("activity_type", activityType));
        }
        query.must(termsQuery("platform_data", TokenUtil.getPlatformData(), "all"));
        if (null != productId) {
            query.mustNot(termQuery("id", productId));
        }
        SearchQuery searchQuery = null;
        if (null != productId) {
            searchQuery = EsUtils.createSearchQuery(query, EsUtils.MIN_SCORE_1, EsConstant.MYSQL_PRODUCT);
        } else {
            searchQuery = EsUtils.createSearchQuery(query, EsUtils.MIN_SCORE_1, EsConstant.MYSQL_PRODUCT);
        }
        List<ProductEsDto> productActivityEsDtoList = esService.query(searchQuery, ProductEsDto.class);
        return productActivityEsDtoList;
    }

    @Override
    public List<HomeRecommendResponse> getRecommendProductList(Integer productId, Integer pageNum, Integer pageSize, UsersResponse usersResponse, String activityType) {


//        Integer sex = null;
        String ageStr = null;
        // 查询当前商品信息
        List<HomeRecommendResponse> productResponseList = new ArrayList<>();
        if (productId != null) {
            ProductResponse productResponse = getProductById(productId, "");
            productResponse.setRecommendImgList(this.getRecommendImgById(productResponse.getId()));
            ProductMatching productMatching = productDao.queryProductMatchingById(productResponse.getId());
            productResponse.setShrinkImg("https://img.quanminyanxuan.com/service/14c7a481d8124ed0a3b8d19beb4075c0.png");
            // 查询Es推荐商品个数
            long count = this.getEsRecommendNum(productMatching);
            productResponse.setSimilaritySum(count);
            productResponse.setPageButton(this.getPageButton("COMMON"));

            if (pageNum == 1) {
                HomeRecommendResponse homeRecommendResponse = new HomeRecommendResponse();
                BeanUtils.copyProperties(productResponse, homeRecommendResponse);
                productResponseList.add(homeRecommendResponse);
            }
            if (StringUtils.isEmpty(activityType)) {
                ageStr = productMatching.getAgeStr();
            }
        }
        log.debug("年龄 ：{},activityType :{} ", ageStr, activityType);

        List<ProductEsDto> productList = this.getProductByAge(productId, ageStr, TokenUtil.getDataType(), pageNum, pageSize, activityType);

//        PageHelper.startPage(pageNum, pageSize);
//        List<Product> productList = productDao.queryRecommendProductList(null, null, TokenUtil.getDataType());
////         普通商品
//        if (productId != null) {
//            productList = productList.stream()
//                    .filter(item -> item.getId().intValue() != productId.intValue())
//                    .collect(Collectors.toList());
//        }


        Collections.shuffle(productList);
        productResponseList.addAll(
                productList.stream()
                        .map(item -> {
                            ProductMatching productMatching = productDao.queryProductMatchingById(item.getId());
                            HomeRecommendResponse response = new HomeRecommendResponse(item);
                            response.setRecommendImgList(this.getRecommendImgByIdV2(item.getId()));
                            response.setPageButton(this.getPageButton("COMMON"));
                            response.setShrinkImg("https://img.quanminyanxuan.com/service/14c7a481d8124ed0a3b8d19beb4075c0.png");
                            if (null == productMatching || StringUtils.isEmpty(productMatching.getLabelJson())) {
                                response.setSimilaritySum(0L);
                            } else {
                                long count = this.getEsRecommendNum(productMatching);
                                response.setSimilaritySum(count);
                            }
                            return response;
                        })
                        .collect(Collectors.toList())
        );
        productResponseList = productResponseList.stream().map(item -> {
            PageButton pageButton = item.getPageButton();
            ProductResponse productResponse = new ProductResponse();
            BeanUtils.copyProperties(item, productResponse);
            if (null != pageButton) {
                pageButton.setCopywriter(this.getCopywriter(productResponse, usersResponse));
                item.setPageButton(pageButton);
            } else {
                log.info("没有pageButton 的商品信息:{}", JSONObject.toJSONString(item));
            }
            //  只有 秒杀  || 以旧换新  || 普通商品 才计算差价
            if ("SECKILL".equals(item.getActivityType()) ||
                    "OLD_FOR_NEW".equals(item.getActivityType()) ||
                    StringUtils.isEmpty(item.getActivityType())) {
                BigDecimal activityMax = item.getOriginalPrice().subtract(item.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                item.setActivityMax(activityMax);
            }
            return item;
        }).collect(Collectors.toList());
        productResponseList = productResponseList.stream()
                .map(item1 -> {
                    // todo
                    item1.setSpecMap(this.getRecommendProductSpecList(item1.getId(), item1.getIsActivity()).stream()
                            .collect(Collectors.toMap(item -> {
                                String skuSpec = item.getSkuSpec();
                                String[] specList = skuSpec.split(",");
                                StringBuilder stringBuilder = new StringBuilder();
                                for (int i = 0; i < specList.length; i++) {
                                    String key = specList[i].split(":")[1];
                                    if (i == specList.length - 1) {
                                        stringBuilder.append(key);
                                    } else {
                                        stringBuilder.append(key).append("-");
                                    }
                                }
                                return stringBuilder.toString();
                            }, item -> item)));
                    return item1;
                }).collect(Collectors.toList());

        return productResponseList;
    }


    /**
     * 获取pageButton
     *
     * @param activityType
     * @return
     */
    @Override
    public PageButton getPageButton(String activityType) {
        PageButtonExample pageButtonExample = new PageButtonExample();
        pageButtonExample.createCriteria()
                .andActivityTypeEqualTo(activityType)
                .andTypeEqualTo("ACTIVITY_BAR");
        List<PageButton> pageButtons = pageButtonMapper.selectByExample(pageButtonExample);
        if (pageButtons.size() > 0) {
            return pageButtons.get(0);
        }
        return null;
    }

    /**
     * 获取Es推荐商品个数
     *
     * @param productMatching
     * @return
     */
    public long getEsRecommendNum(ProductMatching productMatching) {
        // 查询Es推荐商品个数
        BoolQueryBuilder productBoolQueryBuilder = new BoolQueryBuilder();
        if (null != productMatching && StringUtils.isNotEmpty(productMatching.getLabelJson())) {
            productBoolQueryBuilder.must(multiMatchQuery(productMatching.getLabelJson(), "label_json"));
        }
        productBoolQueryBuilder.must(termQuery("status", ProductStatusEnums.UP.getValue()));
        SearchQuery productRecommendQuery = new NativeSearchQueryBuilder()
                .withQuery(productBoolQueryBuilder)
                .withIndices(EsConstant.MYSQL_PRODUCT, EsConstant.MYSQL_PRODUCT_ACTIVITY)
                .build();
        Long count = esService.count(productRecommendQuery);
        return count;
    }


    @Override
    public List<ProductImg> getRecommendImgById(Integer id) {
        ProductImgExample example = new ProductImgExample();
        example.setOrderByClause("sort asc");
        example.createCriteria()
                .andTypeEqualTo(SpecialTypeEnums.recommend.name())
                .andProductIdEqualTo(id);
        List<ProductImg> productImgList = productImgMapper.selectByExample(example);
        return productImgList;
    }

    @Override
    public List<ProductRecommendImgResponse> getRecommendImgByIdV2(Integer id) {
        ProductImgExample example = new ProductImgExample();
        example.setOrderByClause("sort asc");
        example.createCriteria()
                .andTypeEqualTo(SpecialTypeEnums.recommend.name())
                .andProductIdEqualTo(id);
        List<ProductImg> productImgList = productImgMapper.selectByExample(example);
        return productImgList.stream()
                .map(item -> new ProductRecommendImgResponse(item))
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductRecommendImgResponse> getRecommendActivityImgById(Integer productId) {
        ProductActivityImgExample example = new ProductActivityImgExample();
        example.setOrderByClause("sort asc");
        example.createCriteria()
                .andTypeEqualTo(SpecialTypeEnums.recommend.name())
                .andProductIdEqualTo(productId);
        List<ProductActivityImg> productActivityImgList = productActivityImgMapper.selectByExample(example);
        return productActivityImgList.stream()
                .map(item -> new ProductRecommendImgResponse(item))
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductResponse> getHomeRecommendProductList() {
        ProductExample example = new ProductExample();
        example.setOrderByClause("sort desc");
        example.createCriteria()
                .andHomeFlagEqualTo(IsHomeFlagConstant.YES)
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andPlatformDataIn(Arrays.asList(TokenUtil.getPlatformData(), "all"))
                .andAuditStatusEqualTo(ProductAuditStatusEnums.PASS.getValue());
        List<Product> productList = productMapper.selectByExample(example);
        return productList.stream()
                .map(item -> {
                    ProductResponse productResponse = new ProductResponse(item);
                    List<Object> fakeUserList = redisService.range(RedisConstants.FAKE_USER, 0, -1);
                    Collections.shuffle(fakeUserList);
                    List<UsersFake> list = fakeUserList.stream()
                            .map(userItem -> JSONObject.parseObject((String) userItem, UsersFake.class))
                            .limit(3)
                            .collect(Collectors.toList());
                    productResponse.setUsersFakeList(list);
                    productResponse.setShrinkImg("https://img.quanminyanxuan.com/service/14c7a481d8124ed0a3b8d19beb4075c0.png");
                    return productResponse;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductResponse> getHomeRecommendProductV2List() {
        ProductExample example = new ProductExample();
        example.setOrderByClause("sort desc");
        example.createCriteria()
                .andHomeFlagEqualTo(IsHomeFlagConstant.YES)
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andPlatformDataIn(Arrays.asList(TokenUtil.getPlatformData(), "all"));
        List<Product> productList = productMapper.selectByExample(example);
        return productList.stream()
                .map(item -> {
                    ProductResponse productResponse = new ProductResponse(item);
                    productResponse.setRecImgFlag(1);
                    return productResponse;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductResponse> getSpecialRecommendProduct(Integer specialId) {
        List<Product> productList = productDao.querySpecialRecommendProduct(specialId, TokenUtil.getDataType());
        if ("h5".equals(TokenUtil.getSource())) {
            productList = productList.stream()
                    .filter(item -> "h5".equals(item.getPlatformData()) || "all".equals(item.getPlatformData()))
                    .collect(Collectors.toList());
        } else {
            productList = productList.stream()
                    .filter(item -> "app".equals(item.getPlatformData()) || "all".equals(item.getPlatformData()))
                    .collect(Collectors.toList());
        }
        List<ProductResponse> productResponseList = productList.stream()
                .map(ProductResponse::new)
                .collect(Collectors.toList());
        return productResponseList;
    }

    @Resource
    private DynamicMapper dynamicMapper;

    @Override
    public ProductResponse getProductByIdV2(Integer id, int userId, String modular) {
        String key = RedisConstants.PRODUCT_DETAILS + PRODUCT_DETAILS_KEY + id;
        String result = redisService.get(key);
        ProductResponse productResponse;
        if (result != null) {
            productResponse = com.alibaba.fastjson.JSONObject.parseObject(result, ProductResponse.class);
        } else {
            Product product = productMapper.selectByPrimaryKey(id);
            product.setWarehouseName(null);
            Optional.ofNullable(product)
                    .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
            if (product.getStatus().byteValue() != ProductStatusEnums.UP.getValue()) {
                throw new ApiException(ResultCode.NO_PRODUCT);
            }
            String productImgRedisKey = RedisConstants.PRODUCT_DETAILS_IMG + PRODUCT_DETAILS_KEY + id;
            String redisJsonStr = redisService.get(productImgRedisKey);
            if (StringUtils.isEmpty(redisJsonStr)) {
                ProductImgExample example = new ProductImgExample();
                example.setOrderByClause("sort asc");
                example.createCriteria()
                        .andProductIdEqualTo(id);
                List<ProductImg> productImgList = productImgMapper.selectByExample(example);
                Map<String, List<ProductImg>> map = productImgList.stream()
                        .collect(Collectors.groupingBy(ProductImg::getType));
                productResponse = new ProductResponse(product)
                        .setImgMapList(map);

                redisService.set(productImgRedisKey, JSONObject.toJSONString(productImgList));
                redisService.expire(productImgRedisKey, 60);
            } else {
                List<ProductImg> productImgList = JSONArray.parseArray(redisJsonStr, ProductImg.class);
                Map<String, List<ProductImg>> map = productImgList.stream()
                        .collect(Collectors.groupingBy(ProductImg::getType));
                productResponse = new ProductResponse(product).setImgMapList(map);
            }

            productResponse.setPreferentialPrice(productResponse.getOriginalPrice().subtract(productResponse.getPrice()).setScale(0, BigDecimal.ROUND_UP));
            // 优惠券
            if (ActivityTypeEnums.CASH_COUPON.name().equals(product.getActivityType())) {
                productResponse.setCurPrice(product.getPrice().add(productResponse.getActivityMax()).setScale(0, BigDecimal.ROUND_UP));
            }

            if (null != productResponse.getBankerColumnId() && productResponse.getBankerColumnId() == 3) {
                productResponse.setStock(product.getStockEvaluation());// 0元测评用stock_evaluation代替stock
            }
            // 积分商品是否是免费兑的商品
            if (ActivityTypeEnums.CASH_SCORE.name().equals(productResponse.getActivityType())) {
                String freeProduct = sysConfigUtil.getSysConfig("FREE_PRODUCT");
                List<Integer> freeProductId = this.convertType(freeProduct);
                if (freeProductId.contains(productResponse.getId())) {
                    productResponse.setIsFreeProduct(1);
                } else {
                    productResponse.setIsFreeProduct(0);
                }
            }
            redisService.set(key, JSON.toJSONString(productResponse));
            redisService.expire(key, ExpireTimeConstant.PRODUCT_DETAILS_TIME);
        }
        return productResponse;
    }


    @Override
    public List<SearchProductResponse> getActivityList(UsersResponse usersResponse, Integer pageNum, Integer pageSize, String type) {
        List<SearchProductResponse> searchProductResponseList = this.getActivityProducts(pageNum, pageSize, type);
        searchProductResponseList = searchProductResponseList.stream()
                .map(item -> {
                    if (StringUtils.isNotEmpty(item.getActivityType())) {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo(item.getActivityType());
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        if (null != pageButtonList && pageButtonList.size() > 0) {
                            item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                                ProductResponse productResponse = new ProductResponse();
                                BeanUtils.copyProperties(item, productResponse);
                                productResponse.setPageButton(buttonItem);
                                buttonItem.setCopywriter(this.getCopywriter(productResponse, usersResponse));
                                return buttonItem;
                            }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                        }
                    } else {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo("COMMON");
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                            ProductResponse productResponse = new ProductResponse();
                            BeanUtils.copyProperties(item, productResponse);
                            productResponse.setPageButton(buttonItem);
                            buttonItem.setCopywriter(this.getCopywriter(productResponse, usersResponse));
                            return buttonItem;
                        }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                    }
                    return item;
                }).collect(Collectors.toList());
        return searchProductResponseList;
    }

    @Override
    public List<String> selectProductName() {
        return productMapper.selectProductName();
    }

    @Override
    public int selectProduct() {
        return productMapper.selectProduct();
    }

    @Override
    public List<Product> selectExclusive(Integer pageNum,Integer pageSize,Integer type) {
        PageHelper.startPage(pageNum,pageSize);
        return productMapper.selectExclusive(type);
    }

    @Override
    public List<ProductHelpWorkVo> MyExclusive(Integer pageNum, Integer pageSize, Integer type, Integer userId) {
        PageHelper.startPage(pageNum,pageSize);
        List<ProductHelpWorkVo> productHelpWorkVos = productDao.MyExclusive(type, userId);
        productHelpWorkVos.stream().forEach(item ->{
            if (null == item.getAppraisalType()){
                item.setAppraisalType(1);
            }
        });
        return productHelpWorkVos;
    }

    @Override
    public ProductHelpWorkVo MyExclusiveId(Integer Id) {
        return productDao.MyExclusiveId(Id);
    }

    @Override
    public List<SearchProductResponse> getEsRecommendProductList(Integer productId, UsersResponse currentUser, String type, String name, String activityType) {
        Integer searchNum = Integer.valueOf(sysConfigUtil.getSysConfig(SysConfigConstants.SEARCH_NUM));
        List<SearchProductResponse> searchProductResponseList = null;
        if (productId != null) {
            String label = "";
            ProductMatchingExample productMatchingExample = new ProductMatchingExample();
            productMatchingExample.createCriteria()
                    .andProductIdEqualTo(productId);
            List<ProductMatching> productMatchingList = Optional.ofNullable(productMatchingMapper.selectByExampleWithBLOBs(productMatchingExample))
                    .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
            if (productMatchingList.size() > 0) {
                label = productMatchingList.get(0).getLabelJson();
            }
            // 获取活动推荐商品
            searchProductResponseList = this.getActivityProducts(label, "", currentUser, 0, searchNum);
//            Integer productNum = searchProductResponseList.size();
//            if (productNum < searchNum) {
//                List<SearchProductResponse> searchProductResponses = this.getNormalProducts(label, "", currentUser, searchNum, productNum);
//                searchProductResponseList.addAll(searchProductResponses);
//            }
            if ("COMPOSITE".equals(type)) {
            }
            if ("VOLUME".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getVolume).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MAX".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MIN".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice)).collect(Collectors.toList());
            }
        } else {
            String label = "";
            // 获取活动推荐商品
            searchProductResponseList = this.getActivityProducts(label, name, null, 0, searchNum);
//            Integer productNum = searchProductResponseList.size();
            // 获取普通推荐商品
//            if (productNum < searchNum) {
//                List<SearchProductResponse> searchProductResponses = this.getNormalProducts(label, name, null, searchNum, productNum);
//                searchProductResponseList.addAll(searchProductResponses);
//            }
            if ("COMPOSITE".equals(type)) {
            }
            if ("VOLUME".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getVolume).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MAX".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MIN".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice)).collect(Collectors.toList());
            }
        }

        searchProductResponseList = searchProductResponseList.stream()
                .map(item -> {
                    if (StringUtils.isNotEmpty(item.getActivityType())) {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo(item.getActivityType());
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        if (null != pageButtonList && pageButtonList.size() > 0) {
                            item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                                ProductResponse productResponse = new ProductResponse();
                                BeanUtils.copyProperties(item, productResponse);
                                productResponse.setPageButton(buttonItem);
                                buttonItem.setCopywriter(this.getCopywriter(productResponse, currentUser));
                                return buttonItem;
                            }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                        }

                    } else {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo("COMMON");
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                            ProductResponse productResponse = new ProductResponse();
                            BeanUtils.copyProperties(item, productResponse);
                            productResponse.setPageButton(buttonItem);
                            buttonItem.setCopywriter(this.getCopywriter(productResponse, currentUser));
                            return buttonItem;
                        }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                    }
                    return item;
                }).collect(Collectors.toList());
        return searchProductResponseList;

    }

    /**
     * 包含--下架-商品
     *
     * @param productId
     * @param currentUser
     * @param type
     * @param name
     * @param activityType
     * @return
     */
    @Override
    public List<SearchProductResponse> getEsRecommendProductListDown(Integer productId, UsersResponse currentUser, String type, String name, String activityType) {
        Integer searchNum = Integer.valueOf(sysConfigUtil.getSysConfig(SysConfigConstants.SEARCH_NUM));
        List<SearchProductResponse> searchProductResponseList = null;
        if (productId != null) {
            String label = "";
            if (StringUtils.isNotBlank(activityType)) {
                ProductActivityMatchingExample productActivityMatchingExample = new ProductActivityMatchingExample();
                productActivityMatchingExample.createCriteria()
                        .andProductIdEqualTo(productId);
                List<ProductActivityMatching> productActivityMatchingList = Optional.ofNullable(productActivityMatchingMapper.selectByExampleWithBLOBs(productActivityMatchingExample))
                        .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
                if (productActivityMatchingList.size() > 0) {
                    label = productActivityMatchingList.get(0).getLabelJson();
                }
            } else {
                ProductMatchingExample productMatchingExample = new ProductMatchingExample();
                productMatchingExample.createCriteria()
                        .andProductIdEqualTo(productId);
                List<ProductMatching> productMatchingList = Optional.ofNullable(productMatchingMapper.selectByExampleWithBLOBs(productMatchingExample))
                        .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
                if (productMatchingList.size() > 0) {
                    label = productMatchingList.get(0).getLabelJson();
                }
            }
            // 获取活动推荐商品
            searchProductResponseList = this.getActivityProductsDown(label, "", currentUser, 0, searchNum);
            if ("COMPOSITE".equals(type)) {
            }
            if ("VOLUME".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getVolume).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MAX".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MIN".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice)).collect(Collectors.toList());
            }
        } else {
            String label = "";
            // 获取活动推荐商品
            searchProductResponseList = this.getActivityProductsDown(label, name, null, 0, searchNum);
            if ("COMPOSITE".equals(type)) {
            }
            if ("VOLUME".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getVolume).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MAX".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice).reversed()).collect(Collectors.toList());
            }
            if ("PRICE_MIN".equals(type)) {
                searchProductResponseList = searchProductResponseList.stream().sorted(Comparator.comparing(SearchProductResponse::getPrice)).collect(Collectors.toList());
            }
        }
        searchProductResponseList = searchProductResponseList.stream()
                .map(item -> {
                    if (StringUtils.isNotEmpty(item.getActivityType())) {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo(item.getActivityType());
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        if (null != pageButtonList && pageButtonList.size() > 0) {
                            item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                                ProductResponse ProductResponse = new ProductResponse();
                                BeanUtils.copyProperties(item, ProductResponse);
                                ProductResponse.setPageButton(buttonItem);
                                buttonItem.setCopywriter(this.getCopywriter(ProductResponse, currentUser));
                                return buttonItem;
                            }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                        }
                        // 普通商品详情
                        ProductActivityImgExample imgExample = new ProductActivityImgExample();
                        imgExample.setOrderByClause("sort asc");
                        imgExample.createCriteria()
                                .andProductIdEqualTo(item.getId())
                                .andTypeEqualTo("info");
                        List<ProductActivityImg> productImgList = productActivityImgMapper.selectByExample(imgExample);
                        item.setProductActivityImgList(productImgList);
                    } else {
                        PageButtonExample example = new PageButtonExample();
                        example.createCriteria()
                                .andActivityTypeEqualTo("COMMON");
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(example);
                        item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                            ProductResponse productResponse = new ProductResponse();
                            BeanUtils.copyProperties(item, productResponse);
                            productResponse.setPageButton(buttonItem);
                            buttonItem.setCopywriter(this.getCopywriter(productResponse, currentUser));
                            return buttonItem;
                        }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                        // 普通商品详情
                        ProductImgExample imgExample = new ProductImgExample();
                        imgExample.setOrderByClause("sort asc");
                        imgExample.createCriteria()
                                .andProductIdEqualTo(item.getId())
                                .andTypeEqualTo("info");
                        List<ProductImg> productImgList = productImgMapper.selectByExample(imgExample);
                        item.setProductImgList(productImgList);
                    }
                    return item;
                }).collect(Collectors.toList());
        return searchProductResponseList;

    }

    /**
     * 转换按钮数据
     *
     * @param activityResponse
     * @return
     */
    @Override
    public String getCopywriter(ProductResponse activityResponse, UsersResponse usersResponse) {
        String oldCopywriter = "";
        BigDecimal max = BigDecimal.ZERO;
        String activityType = "";
        if (activityResponse != null && activityResponse.getPageButton() != null) {
            // 数据库配置文案
            oldCopywriter = activityResponse.getPageButton().getCopywriter();
            // 积分/红包/抵扣券
            max = activityResponse.getActivityMax();
            // 活动类型
            activityType = activityResponse.getActivityType();
        }
        // 用户积分
        Integer userScore = Integer.valueOf(sysConfigUtil.getSysConfig(SysConfigConstants.DEFAULT_SCORE));
        if (null != usersResponse) {
            log.debug(JSONObject.toJSONString(usersResponse));
            userScore = usersResponse.getScore();
        }
        // 平台补贴
        BigDecimal allowance = activityResponse.getOriginalPrice().subtract(activityResponse.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
        // 商品立减


        // 以旧换新
        if (ActivityTypeEnums.OLD_FOR_NEW.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        // 秒杀
        if (ActivityTypeEnums.SECKILL.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        // 百亿补贴
        if (ActivityTypeEnums.SUBSIDY.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 优惠劵
        if (ActivityTypeEnums.CASH_COUPON.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 红包返现
        if (ActivityTypeEnums.RETURN_CASH.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 积分中心
        if (ActivityTypeEnums.CASH_SCORE.name().equals(activityType)) {
            return oldCopywriter.replace("SCORE", userScore + "").replace("PRICE", allowance.stripTrailingZeros().toPlainString());
        }
        // 返积分
        if (ActivityTypeEnums.GET_SCORE.name().equals(activityType)) {
            return oldCopywriter.replace("SCORE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 新人全返
        if (ActivityTypeEnums.NEW_USER.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        if (StringUtils.isEmpty(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        return oldCopywriter;
    }

    /**
     * 转换按钮数据
     *
     * @param activityResponse
     * @return
     */
    @Override
    public String getCopywriter(ProductExtResponse activityResponse, UsersResponse usersResponse) {
        String oldCopywriter = "";
        BigDecimal max = BigDecimal.ZERO;
        String activityType = "";
        if (activityResponse != null) {
            // 数据库配置文案
            oldCopywriter = activityResponse.getPageButton().getCopywriter();
            // 积分/红包/抵扣券
            max = activityResponse.getActivityMax();
            // 活动类型
            activityType = activityResponse.getActivityType();
        }
        // 用户积分
        Integer userScore = Integer.valueOf(sysConfigUtil.getSysConfig(SysConfigConstants.DEFAULT_SCORE));
        if (null != usersResponse) {
            log.info(JSONObject.toJSONString(usersResponse));
            userScore = usersResponse.getScore();
        }
        // 平台补贴
        BigDecimal allowance = activityResponse.getOriginalPrice().subtract(activityResponse.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
        // 商品立减


        // 以旧换新
        if (ActivityTypeEnums.OLD_FOR_NEW.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        // 秒杀
        if (ActivityTypeEnums.SECKILL.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        // 百亿补贴
        if (ActivityTypeEnums.SUBSIDY.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 优惠劵
        if (ActivityTypeEnums.CASH_COUPON.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 红包返现
        if (ActivityTypeEnums.RETURN_CASH.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 积分中心
        if (ActivityTypeEnums.CASH_SCORE.name().equals(activityType)) {
            return oldCopywriter.replace("SCORE", userScore + "").replace("PRICE", allowance.stripTrailingZeros().toPlainString());
        }
        // 返积分
        if (ActivityTypeEnums.GET_SCORE.name().equals(activityType)) {
            return oldCopywriter.replace("SCORE", max.stripTrailingZeros().toPlainString() + "");
        }
        // 新人全返
        if (ActivityTypeEnums.NEW_USER.name().equals(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        if (StringUtils.isEmpty(activityType)) {
            return oldCopywriter.replace("PRICE", allowance.stripTrailingZeros().toPlainString() + "");
        }
        return oldCopywriter;
    }

    @Override
    public List<SearchProductResponse> getHotRecommend(UsersResponse currentUser, Integer pageNum, Integer pageSize, String type) {
        PageHelper.startPage(1, 10);
        List<SearchProductResponse> searchProductResponseList;
        if (!TokenUtil.getRequest().getHeader("source").equals("h5")) {
            searchProductResponseList = this.getActivityProducts(pageNum, pageSize, type);
        } else {
            searchProductResponseList = this.getActivityProducts(pageNum, pageSize, type);
        }
        searchProductResponseList = searchProductResponseList.stream()
                .map(item -> {
                    if (StringUtils.isNotEmpty(item.getActivityType())) {
                        PageButtonExample pageButtonExample = new PageButtonExample();
                        pageButtonExample.createCriteria()
                                .andActivityTypeEqualTo(item.getActivityType());
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(pageButtonExample);
                        if (null != pageButtonList && pageButtonList.size() > 0) {
                            item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                                ProductResponse productResponse = new ProductResponse();
                                BeanUtils.copyProperties(item, productResponse);
                                productResponse.setPageButton(buttonItem);
                                buttonItem.setCopywriter(this.getCopywriter(productResponse, currentUser));
                                return buttonItem;
                            }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                        }
                    } else {
                        PageButtonExample pageButtonExample = new PageButtonExample();
                        pageButtonExample.createCriteria()
                                .andActivityTypeEqualTo("COMMON");
                        List<PageButton> pageButtonList = pageButtonMapper.selectByExample(pageButtonExample);
                        item.setPageButtonMap(pageButtonList.stream().map(buttonItem -> {
                            ProductResponse productResponse = new ProductResponse();
                            BeanUtils.copyProperties(item, productResponse);
                            productResponse.setPageButton(buttonItem);
                            buttonItem.setCopywriter(this.getCopywriter(productResponse, currentUser));
                            return buttonItem;
                        }).collect(Collectors.toMap(PageButton::getType, a -> a, (k1, k2) -> k1)));
                    }
                    item.setPrice(new BigDecimal(item.getPrice().stripTrailingZeros().toPlainString()));
                    item.setOriginalPrice(new BigDecimal(item.getOriginalPrice().stripTrailingZeros().toPlainString()));
                    return item;
                }).collect(Collectors.toList());

        if (searchProductResponseList != null && searchProductResponseList.size() > 0) {
            return shuffle(searchProductResponseList);
        }
        return searchProductResponseList;
    }

    private List<SearchProductResponse> shuffle(List<SearchProductResponse> list) {
        List<Integer> is = new ArrayList<Integer>();
        for (int i = 0; i < list.size(); i++) {
            is.add(new Integer(i));
        }
        Collections.shuffle(is);
        List<SearchProductResponse> res = new ArrayList<>();
        for (Integer j : is) {
            res.add(list.get(j));
        }
        return res;
    }

    @Override
    public void recordProductBrowe(Integer productId, String activityType, Integer userId, String pageSourceV2) {
        ProductBroweRecordResponse productBroweRecordResponse = new ProductBroweRecordResponse();
        productBroweRecordResponse.setUserId(userId);
        productBroweRecordResponse.setModular(pageSourceV2);
        Product product = productDao.getProductById(productId);
        BeanUtils.copyProperties(product, productBroweRecordResponse);
        productBroweRecordResponse.setProductId(product.getId());
        productRecordUtil.productRecord(productBroweRecordResponse);
    }

    @Override
    public List<ProductReviewsResponse> getProductReviews(Integer productId) {
        List<ProductReviews> productReviews;
        if (productId != null) {
            ProductReviewsExample productReviewsExample = new ProductReviewsExample();
            productReviewsExample.createCriteria().andProductIdEqualTo(productId).andIsShowEqualTo(1);
            productReviews = productReviewsMapper.selectByExample(productReviewsExample);
        } else {
            ProductReviewsExample example = new ProductReviewsExample();
            example.createCriteria().andIsShowEqualTo(1);
            productReviews = productReviewsMapper.selectByExample(example);
        }

        List<ProductReviews> list = productReviewsMapper.queryProductReviews();
        Collections.shuffle(list);
        productReviews.addAll(list);
//        Collections.shuffle(productReviews);
        List<ProductReviewsResponse> productReviewsResponse = new ArrayList<>();
        if (!CollectionUtils.isEmpty(productReviews)) {
            productReviews.stream().forEach(item -> {
                ProductReviewsResponse data = new ProductReviewsResponse(item);
                productReviewsResponse.add(data);
            });
        }
        return productReviewsResponse;
    }

    @Override
    public BuyRecordResponse getBuyRecordById(Integer productId) {
        BuyRecordResponse data = new BuyRecordResponse();
        Product product = productMapper.selectByPrimaryKey(productId);
        if (ActivityTypeEnums.OLD_FOR_NEW.name().equals(product.getActivityType())) {
            BigDecimal originalPrice = product.getOriginalPrice();
            BigDecimal activityMax = product.getActivityMax();
            List<UsersFake> usersFakeList = fakeUserUtil.getFakeUserList();
            usersFakeList.stream()
                    .map(item -> {
                        double receivePrice = RandomUtil.getNextDouble(activityMax.intValue() * 0.9, activityMax.doubleValue());
                        BigDecimal money = new BigDecimal(receivePrice);
                        // 领取了多少元
                        item.setTotalMoney(money.setScale(2, BigDecimal.ROUND_DOWN));
                        // 花了多少元购买
                        BigDecimal pay = originalPrice.subtract(money);
                        item.setMoney(pay.setScale(2, BigDecimal.ROUND_UP));
                        return item;
                    }).collect(Collectors.toList());
            data.setFakeUserList(usersFakeList);
            data.setNum(RandomUtil.getSectionNum(1000, 2000));
            return data;
        }
        return null;
    }

    /**
     * @Description 获取活动推荐商品
     *
     *
     * @Version 1.0
     **/
    public List<SearchProductResponse> getActivityProducts(String label, String name, UsersResponse currentUser, Integer pageNum, Integer pageSize) {
        // 搜索类型
        String type = sysConfigUtil.getSysConfig("SEARCH_TYPE");
        List<String> searchType = Arrays.asList(type.split(","));
        BoolQueryBuilder activityBoolQueryBuilder = null;
        if (currentUser != null) {
            activityBoolQueryBuilder = new MyBoolQueryBuilder(pageNum, pageSize);
            activityBoolQueryBuilder.must(termQuery("status", ProductStatusEnums.UP.getValue() + ""));
            activityBoolQueryBuilder.must(termQuery("data_type", TokenUtil.getDataType()));
            activityBoolQueryBuilder.must(termQuery("is_advert", "0"));
            activityBoolQueryBuilder.must(termQuery("is_hide", "0"));
            activityBoolQueryBuilder.must(termsQuery("platform_data", "all", PlatformDataUtils.getPlatformData(TokenUtil.getSource())));
            if (StringUtils.isNotEmpty(label)) {
                activityBoolQueryBuilder.must(multiMatchQuery(label, "label_json"));
            }
            if (StringUtils.isNotEmpty(name)) {
                activityBoolQueryBuilder.must(multiMatchQuery(name, "product_name"));
            }
        } else {
            activityBoolQueryBuilder = new MyBoolQueryBuilder(pageNum, pageSize)
                    .must(termQuery("data_type", TokenUtil.getDataType()))
                    .must(termQuery("status", ProductStatusEnums.UP.getValue() + ""))
                    .must(termQuery("is_advert", "0"))
                    .must(termsQuery("platform_data", "all", PlatformDataUtils.getPlatformData(TokenUtil.getSource())))
                    .must(termQuery("is_hide", "0"))
                    .must(multiMatchQuery(name, "product_name"));
        }
        SearchQuery searchQuery = EsUtils.createSearchQuery(activityBoolQueryBuilder, EsUtils.MIN_SCORE, EsConstant.MYSQL_PRODUCT);
        List<ProductEsDto> productEsDtoList = esService.query(searchQuery, ProductEsDto.class);
        productEsDtoList = productEsDtoList.stream()
                .filter(item -> {
                    if (StringUtils.isEmpty(item.getActivityType())) {
                        return true;
                    }
                    return searchType.contains(item.getActivityType());
                }).collect(Collectors.toList());
        List<SearchProductResponse> searchProductResponseList = productEsDtoList
                .stream()
                .filter(item -> item.getStatus() == ProductStatusEnums.UP.getValue())
                .filter(item -> {
                    if (ActivityTypeEnums.SECKILL.name().equals(item.getActivityType())) {
                        if (item.getColumnId().intValue() == 4) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true;
                    }
                }).map(SearchProductResponse::new).collect(Collectors.toList());
        return searchProductResponseList;
    }

    /**
     * @Description 获取活动推荐《下架》商品
     *
     *
     * @Version 1.0
     **/
    public List<SearchProductResponse> getActivityProductsDown(String label, String name, UsersResponse currentUser, Integer pageNum, Integer pageSize) {
        // 搜索类型
        String type = sysConfigUtil.getSysConfig("SEARCH_TYPE");
        List<String> searchType = Arrays.asList(type.split(","));
        BoolQueryBuilder activityBoolQueryBuilder = null;
        if (currentUser != null) {
            activityBoolQueryBuilder = new MyBoolQueryBuilder(pageNum, pageSize);
            activityBoolQueryBuilder.must(termQuery("data_type", TokenUtil.getDataType()));
            activityBoolQueryBuilder.must(termQuery("is_advert", "0"));
            activityBoolQueryBuilder.must(termQuery("is_hide", "0"));
            if (StringUtils.isNotEmpty(label)) {
                activityBoolQueryBuilder.must(multiMatchQuery(label, "label_json"));
            }
            if (StringUtils.isNotEmpty(name)) {
                activityBoolQueryBuilder.must(multiMatchQuery(name, "product_name"));
            }
        } else {
            activityBoolQueryBuilder = new MyBoolQueryBuilder(pageNum, pageSize)
                    .must(termQuery("data_type", TokenUtil.getDataType()))
                    .must(termQuery("is_advert", "0"))
                    .must(termQuery("is_hide", "0"))
                    .must(multiMatchQuery(name, "product_name"));
        }
        SearchQuery searchQuery = EsUtils.createSearchQuery(activityBoolQueryBuilder, EsUtils.MIN_SCORE, EsConstant.MYSQL_PRODUCT, EsConstant.MYSQL_PRODUCT_ACTIVITY);
        List<ProductActivityEsDto> productActivityEsDtoList = esService.query(searchQuery, ProductActivityEsDto.class);
        productActivityEsDtoList = productActivityEsDtoList.stream()
                .filter(item -> {
                    if (StringUtils.isEmpty(item.getActivityType())) {
                        return true;
                    }
                    return searchType.contains(item.getActivityType());
                }).collect(Collectors.toList());
        List<SearchProductResponse> searchProductResponseList = productActivityEsDtoList
                .stream()
                .filter(item -> item.getStatus() == ProductStatusEnums.UP.getValue())
                .filter(item -> {
                    if (ActivityTypeEnums.SECKILL.name().equals(item.getActivityType())) {
                        if (item.getColumnId().intValue() == 4) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true;
                    }
                }).map(SearchProductResponse::new).collect(Collectors.toList());
        return searchProductResponseList;
    }

    @Override
    public List<Product> queryGuessLikeByActivity(Integer pageNum, Integer pageSize, Integer productId, String activityType) {
        PageHelper.startPage(pageNum, pageSize + 1);
        List<Product> products = productDao.queryActivityProductList(activityType, null, null, null, null, TokenUtil.getPlatformData(), null,null,null,null);
        products = products.stream().filter(s -> !s.getId().equals(productId)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(products) && products.size() > 6) {
            products = products.subList(0, 6);
        }
        if (ActivityTypeEnums.GROUP_WORK.name().equals(activityType)) {
            List<Integer> productIds = products.stream().map(Product::getId).collect(Collectors.toList());
            List<ProductGroupBuyInfo> groupBuyInfoList = yxProductGroupBuyInfoService.queryByProductIds(productIds);
            products.stream().forEach(item -> {
                if (CollectionUtils.isEmpty(groupBuyInfoList)) {
                    item.setBalance(BigDecimal.ZERO);
                    return;
                }
                List<ProductGroupBuyInfo> newList = groupBuyInfoList.stream().filter(pro -> pro.getProductId().equals(item.getId())).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(newList)) {
                    item.setBalance(BigDecimal.ZERO);
                    return;
                }
                ProductGroupBuyInfo matchObj = newList.get(0);
                if (2 == matchObj.getDivideWay()) {
                    item.setBalance(matchObj.getFixedPrice());
                }else {
                    item.setBalance(calculationBalance(matchObj.getRatio(), item.getCurPrice(), item.getCostPrice(), matchObj.getMinPerson()));
                }
            });
        }
        products.stream().forEach(item -> {
            ProductImgExample example = new ProductImgExample();
            example.setOrderByClause("sort asc");
            example.createCriteria()
                    .andProductIdEqualTo(item.getId());
            List<ProductImg> imgs = productImgMapper.selectByExample(example);
            item.setImgs(imgs.stream().filter(img -> "banner".equals(img.getType())).map(img -> img.getImgUrl()).limit(3).collect(Collectors.toList()));
        });

        return products;
    }


    private BigDecimal calculationBalance(String ratio, BigDecimal groupPrice, BigDecimal costPrice, Integer minPerson) {
        BigDecimal grossProfit = groupPrice.subtract(costPrice);
        BigDecimal balance = grossProfit.multiply(BigDecimal.valueOf(Long.valueOf(ratio))).divide(new BigDecimal(100), 0, BigDecimal.ROUND_HALF_UP);
        return balance.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : balance;
    }

    @Override
    public List<Product> queryGuessLikeByNormal(Integer pageNum, Integer pageSize, Integer productId) {
        PageHelper.startPage(pageNum, pageSize + 1);
        List<Product> products = productDao.queryActivityProductList(null, null, null, null, null, TokenUtil.getPlatformData(), null,null,null,null);
        products = products.stream().filter(s -> !s.getId().equals(productId)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(products) && products.size() > 6) {
            products = products.subList(0, 6);
        }
        products.stream().forEach(item -> {
            ProductImgExample example = new ProductImgExample();
            example.setOrderByClause("sort asc");
            example.createCriteria()
                    .andProductIdEqualTo(item.getId());
            List<ProductImg> imgs = productImgMapper.selectByExample(example);
            item.setImgs(imgs.stream().filter(img -> "banner".equals(img.getType())).map(img -> img.getImgUrl()).limit(3).collect(Collectors.toList()));
        });
        return products;
    }

    public List<SearchProductResponse> getActivityProducts(Integer pageNum, Integer pageSize, String sortType) {
        // 搜索类型
        BoolQueryBuilder activityBoolQueryBuilder = new MyBoolQueryBuilder(pageNum - 1, pageSize)
                .must(termQuery("product_type", 2))
                .must(termQuery("data_type", TokenUtil.getDataType()))
                .must(termQuery("is_advert", "0"))
                .must(termQuery("is_hide", "0"))
                .must(termsQuery("platform_data", "all", PlatformDataUtils.getPlatformData(TokenUtil.getSource())))
                .must(termQuery("status", ProductStatusEnums.UP.getValue() + ""))
                .mustNot(matchQuery("activity_type", ActivityTypeEnums.RECHARGE_COUPON.name()))
                .mustNot(matchQuery("activity_type", ActivityTypeEnums.CASH_SCORE.name()));// 根据条件是会查出积分的,要求加以筛除
        SearchQuery searchQuery = EsUtils.createSearchQuery(activityBoolQueryBuilder, EsUtils.MIN_SCORE_1, EsConstant.MYSQL_PRODUCT);
        List<ProductEsDto> productEsDtoList = esService.query(searchQuery, ProductEsDto.class);
        List<SearchProductResponse> searchProductResponseList = productEsDtoList
                .stream().map(SearchProductResponse::new)
                .collect(Collectors.toList());
//         Collections.shuffle(searchProductResponseList);
        return searchProductResponseList;
    }

    /**
     * @Description 获取普通推荐商品
     *
     *
     * @Version 1.0
     **/
    public List<SearchProductResponse> getNormalProducts(String label, String name, UsersResponse currentUser, Integer searchNum, Integer productNum) {
        BoolQueryBuilder productBoolQueryBuilder = null;
        if (currentUser != null) {
            productBoolQueryBuilder = new BoolQueryBuilder();
            if (StringUtils.isNotEmpty(label)) {
                productBoolQueryBuilder.must(multiMatchQuery(label, "label_json"));
            }
            if (StringUtils.isNotEmpty(currentUser.getAgeStr())) {
                productBoolQueryBuilder.must(multiMatchQuery(currentUser.getAgeStr(), "age_str"));
            }
            if (StringUtils.isNotEmpty(name)) {
                productBoolQueryBuilder.must(multiMatchQuery(name, "product_name"));
            }
            productBoolQueryBuilder.must(termQuery("status", ProductStatusEnums.UP.getValue()));

        } else {
            productBoolQueryBuilder = new BoolQueryBuilder()
                    .must(multiMatchQuery(name, "product_name"))
                    .must(termQuery("status", ProductStatusEnums.UP.getValue()));
        }
        Pageable pageable = PageRequest.of(0, searchNum - productNum);
        SearchQuery normalProductSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(productBoolQueryBuilder)
                .withPageable(pageable)
                .build();
        List<ProductEsDto> productEsDtoList = template.queryForList(normalProductSearchQuery, ProductEsDto.class);
        List<SearchProductResponse> searchProductResponses = productEsDtoList.stream().map(SearchProductResponse::new).collect(Collectors.toList());
        return searchProductResponses;
    }

    @Override
    public CommonResult getList(Integer pageNum, Integer pageSize, String productName) {
        String key = RedisConstants.PRODUCTLIST + pageNum + pageSize + productName + ":";
        PageHelper.startPage(pageNum, pageSize);
        Boolean exist = redisService.hasKey(key);
        if (exist) {
            return JSONObject.parseObject(redisService.get(key), CommonResult.class);
        }
        List<ProductListResponse> list = productDao.findList(productName);
        CommonResult<ProductListResponse> page = CommonResult.page(list);
        redisService.set(key, JSONObject.toJSONString(page));
        redisService.expire(key, 120);
        return page;
    }

    @Override
    public List<ProductShortResponse> getBrandPdInProductDetails(Integer productId) {
//        Map<String, Object> data = new HashMap<>();
        List<ProductShortResponse> brandPdInProductDetail;

        String key = RedisConstants.PRODUCT_DETAILS + PRODUCT_DETAILS_KEY + BRAND_PRODUCT_IN_PRODUCT_DETAILS + TokenUtil.getPlatformData() + productId;
        String result = redisService.get(key);
        if (result != null) {
//            data = JSONObject.parseObject(result, Map.class);
            brandPdInProductDetail = JSONArray.parseArray(result, ProductShortResponse.class);
        } else {
            Product product = productMapper.selectByPrimaryKey(productId);
            Optional.ofNullable(product)
                    .orElseThrow(() -> new ApiException(copyWriterConfigUtil.getCopyWriterValue(CopyWriterConstant.COMMODITY_NOT_EXIST)));
            if (product.getStatus().byteValue() != ProductStatusEnums.UP.getValue()) {
                throw new ApiException(ResultCode.NO_PRODUCT);
            }

            // 店铺推荐相关信息
            Integer brandId = product.getBrandId();
//            data.put("brandId", brandId);
            // 店铺商品
            int limitNum = 12;
//            int limitNum = Integer.valueOf(sysConfigUtil.getSysConfig("BRAND_PD_NUM_IN_PD_DETAIL"));
            brandPdInProductDetail = this.getProductsbyBrandId(brandId, limitNum, productId);
//            data.put("brandPdInProductDetail", brandPdInProductDetail);

            redisService.set(key, JSON.toJSONString(brandPdInProductDetail));
            redisService.expire(key, ExpireTimeConstant.PRODUCT_DETAILS_TIME);
        }
        return brandPdInProductDetail;
    }

    private BrandProductResponse getBrandInfoByBrandId(Integer brandId) {
        BrandProductResponse brandProductResponse = new BrandProductResponse();
        if (brandId != null) {
            brandProductResponse = Optional.ofNullable(productDao.getBrandInfoByBrandId(brandId))
                    .orElse(new BrandProductResponse());
        }
        return brandProductResponse;
    }

    @Override
    public List<ProductShortResponse> getFeikePdInProductDetails() {
        ProductExample productExample = new ProductExample();

        productExample.setOrderByClause("sort desc");
        productExample.createCriteria()
                .andIdIn(Arrays.asList(608, 2135, 2136, 2138, 2144, 2393, 2395, 2396, 2401, 2402, 2416, 5745))// 飞克品牌商品id
//                .andIdIn(this.convertType(sysConfigUtil.getSysConfig("FEIKE_PRODUCT")))// 飞克品牌商品id
                .andStatusEqualTo(ProductStatusEnums.UP.getValue())
                .andPlatformDataIn(Arrays.asList("all", TokenUtil.getPlatformData()));
        List<Product> feikeProducts = productMapper.selectByExample(productExample);

        List<ProductShortResponse> feikeProductList =
                feikeProducts.stream()
                        .map(ProductShortResponse::new)
                        .collect(Collectors.toList());

        return feikeProductList;
    }

    private List<ProductShortResponse> getProductsbyBrandId(Integer brandId, int limitNum, Integer productId) {

        return Optional.ofNullable(productDao.getProductsbyBrandId(brandId, TokenUtil.getPlatformData(), limitNum, productId))
                .orElse(new ArrayList<>());

    }


    @Override
    public List<ProductResponse> getConfigProductList(String key) {
        String ids = sysConfigUtil.getSysConfig(key);
        String[] split = ids.split(",");
        List<String> strings = Arrays.asList(split);
        return productDao.findByIds(strings);
    }

    @Override
    public List<ProductResponse> getSpecialProductList(Integer pageNum, Integer pageSize, Integer specialId, String activityType, String platformData, String consumerPower) {
        PageHelper.startPage(pageNum, pageSize);
        //人群消费能力,取值HIGN,LOW
        if (!"HIGN".equalsIgnoreCase(consumerPower) && !"LOW".equalsIgnoreCase(consumerPower)) {
            consumerPower = null;
        }
        return productDao.findBySpecialIdAndActivity(specialId, activityType, platformData, consumerPower);
    }

    @Override
    public List<ProductResponse> getProductByActivityTypeAndLimit(String activityType, Integer limit) {
        ProductExample example = new ProductExample();
        example.createCriteria().andActivityTypeEqualTo(activityType)
                .andStatusEqualTo(ProductStatusEnums.UP.getValue());
        example.setOrderByClause("sort");
        return null;
    }

    @Override
    public CommonResult getHighestVolumeProduct() {
        List<HighestVolumeProductVO> products = productDao.selectByHighestVolume();
        return CommonResult.success(products);
    }

    @Override
    public String selectProductImagesByActivityTypeLimit(String activityTypes, Integer size) {
        List<Product> list = productDao.selectProductImagesByActivityTypeLimit(activityTypes, size, "h5");
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        String result = Joiner.on(",").join(list.stream().map(Product::getProductImg).collect(Collectors.toList()));
        return result;
    }

    @Override
    public List<Product> selectProductByActivityTypeLimit(String activityType, Integer size) {
        List<Product> list = productDao.selectProductImagesByActivityTypeLimit(activityType, size, "h5");
        return list;
    }
//
//    @Override
//    public List<Product> selectProductImagesByActivityType(List<String> activityTypes) {
//        List<Product> list = productDao.selectProductImagesByActivityType(activityTypes, "h5");
//        return list;
//    }

    /**
     * 查询活动商品的虚拟销量
     * @param activityType
     * @return
     */
    @Override
    public Integer sumProductVolumeByActivityType(String activityType) {
        return productDao.sumProductVolumeByActivityType(activityType);
    }

    @Override
    public void savaRedpacket(Integer productId) {
        String token = TokenUtil.getToken();
        if (StringUtils.isNotBlank(token)){
            //同一个token同一个商品一天只记录一次
            int count = productDao.countRedpacket(token,productId);
            if (count == 0){
                Product product = productDao.getProductById(productId);
                String redpacket ="";
                if (product != null && product.getPrice()!=null && product.getOriginalPrice()!=null){
                    redpacket = (product.getOriginalPrice().subtract(product.getPrice())).toString();
                }
                productDao.savaRedpacket(productId,token,redpacket);
            }
        }

    }

}
